diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java
index a5299967ae1..ff05296897e 100644
--- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java
@@ -114,6 +114,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTForStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionWithTryBlock;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTIfStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceAlias;
@@ -157,7 +158,7 @@ import org.eclipse.text.edits.TextEdit;
* Some heuristic is applied in case of syntax errors or other problems
* to skip those areas, but because of incomplete location information
* the formatting may fail. The reason of the failure is logged.
- *
+ *
* @since 4.0
*/
public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, ICASTVisitor {
@@ -827,7 +828,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
/**
* Determine whether the given declarator is the first in a list of declarators (if any).
- *
+ *
* @param node the declarator node
* @return true
if this node is the first in a list
*/
@@ -1527,7 +1528,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
/**
* Returns the position of the last character of a node, or -1 if that character is part of
* a macro expansion.
- *
+ *
* @param node an AST node
* @return the position of the last character of a node, or -1 if that character is part of
* a macro expansion.
@@ -1658,12 +1659,16 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
Runnable tailFormatter = fExpectSemicolonAfterDeclaration ?
new TrailingSemicolonFormatter(node) : null;
if (declarators.size() == 1) {
- scribe.setTailFormatter(tailFormatter);
- try {
+ if (tailFormatter != null) {
+ scribe.setTailFormatter(tailFormatter);
+ try {
+ visit(declarators.get(0));
+ scribe.runTailFormatter();
+ } finally {
+ scribe.setTailFormatter(null);
+ }
+ } else {
visit(declarators.get(0));
- scribe.runTailFormatter();
- } finally {
- scribe.setTailFormatter(null);
}
} else {
final ListOptions options= new ListOptions(preferences.alignment_for_declarator_list);
@@ -2047,7 +2052,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
* @param encloseInParen indicates whether the list should be enclosed in parentheses
* @param addEllipsis indicates whether ellipsis should be added after the last element
* @param tailFormatter formatter for the trailing text that should be kept together with
- * the last element of the list.
+ * the last element of the list.
*/
private void formatList(List extends IASTNode> elements, ListOptions options,
boolean encloseInParen, boolean addEllipsis, Runnable tailFormatter) {
@@ -2153,12 +2158,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
}
final IASTDeclaration decl= node.getDeclaration();
if (decl != null) {
- fExpectSemicolonAfterDeclaration= false;
- try {
- decl.accept(this);
- } finally {
- fExpectSemicolonAfterDeclaration= true;
- }
+ formatInlineDeclaration(decl);
} else if (node.isCatchAll()) {
scribe.printNextToken(Token.tELIPSE, false /* preferences.insert_space_before_ellipsis */);
// if (false /* preferences.insert_space_after_ellipsis */) {
@@ -2173,6 +2173,15 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
return PROCESS_SKIP;
}
+ private void formatInlineDeclaration(final IASTDeclaration decl) {
+ fExpectSemicolonAfterDeclaration= false;
+ try {
+ decl.accept(this);
+ } finally {
+ fExpectSemicolonAfterDeclaration= true;
+ }
+ }
+
private int visit(IASTCompoundStatement node) {
formatBlock(node, preferences.brace_position_for_block, preferences.insert_space_before_opening_brace_in_block, preferences.indent_statements_compare_to_block);
return PROCESS_SKIP;
@@ -2288,7 +2297,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
/**
* Formats given expressions as a function call, ie. enclosed in parenthesis.
- *
+ *
* @param args the argument expressions, may be null
*/
private void formatFunctionCallArguments(IASTInitializerClause[] args) {
@@ -2785,7 +2794,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
}
private boolean isOverloadedLeftShift(IASTBinaryExpression node) {
- return node.getOperator() == IASTBinaryExpression.op_shiftLeft &&
+ return node.getOperator() == IASTBinaryExpression.op_shiftLeft &&
node instanceof ICPPASTBinaryExpression &&
((ICPPASTBinaryExpression) node).getOverload() != null;
}
@@ -3079,14 +3088,29 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
}
private int visit(IASTForStatement node) {
- scribe.printNextToken(Token.t_for);
- final int line = scribe.line;
- scribe.printNextToken(Token.tLPAREN, preferences.insert_space_before_opening_paren_in_for);
- fInsideFor= true;
- if (preferences.insert_space_after_opening_paren_in_for) {
- scribe.space();
+ if (!startsWithMacroExpansion(node)) {
+ scribe.printNextToken(Token.t_for);
}
+ final int line = scribe.line;
IASTStatement initializerStmt= node.getInitializerStatement();
+ IASTStatement body = node.getBody();
+ Runnable tailFormatter = null;
+ if (!doNodesHaveSameOffset(node, initializerStmt)) {
+ scribe.printNextToken(Token.tLPAREN, preferences.insert_space_before_opening_paren_in_for);
+ fInsideFor= true;
+ if (preferences.insert_space_after_opening_paren_in_for) {
+ scribe.space();
+ }
+ if (DefaultCodeFormatterConstants.END_OF_LINE.equals(preferences.brace_position_for_block) &&
+ body instanceof IASTCompoundStatement && !startsWithMacroExpansion(body)) {
+ tailFormatter = new TrailingTokenFormatter(Token.tLBRACE,
+ body.getFileLocation().getNodeOffset(),
+ preferences.insert_space_before_opening_brace_in_block, false);
+ }
+ tailFormatter = new ClosingParensesisTailFormatter(
+ preferences.insert_space_before_closing_paren_in_for, tailFormatter);
+ }
+
initializerStmt.accept(this);
if (peekNextToken() == Token.tSEMI) {
scribe.printNextToken(Token.tSEMI, preferences.insert_space_before_semicolon_in_for);
@@ -3124,6 +3148,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
scribe.printNextToken(Token.tSEMI, preferences.insert_space_before_semicolon_in_for);
}
+ scribe.setTailFormatter(tailFormatter);
scribe.alignFragment(alignment, 1);
IASTExpression iterationExpr= node.getIterationExpression();
if (iterationExpr != null) {
@@ -3132,52 +3157,62 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
}
iterationExpr.accept(this);
}
+ if (tailFormatter != null) {
+ scribe.runTailFormatter();
+ scribe.setTailFormatter(null);
+ }
} finally {
fInsideFor= false;
}
- if (peekNextToken() == Token.tRPAREN) {
- scribe.printNextToken(Token.tRPAREN, preferences.insert_space_before_closing_paren_in_for);
- }
- IASTStatement body = node.getBody();
- if (body instanceof IASTCompoundStatement && !startsWithMacroExpansion(body)) {
- formatLeftCurlyBrace(line, preferences.brace_position_for_block);
- if (startNode(body)) {
- try {
- final boolean braceOnSameLine = DefaultCodeFormatterConstants.END_OF_LINE.equals(preferences.brace_position_for_block);
- if (!braceOnSameLine) {
- ok = true;
- scribe.exitAlignment(alignment, true);
- }
- formatBlockOpening((IASTCompoundStatement) body,
- preferences.brace_position_for_block,
- preferences.insert_space_before_opening_brace_in_block);
- if (braceOnSameLine) {
- ok = true;
- scribe.exitAlignment(alignment, true);
- }
- formatOpenedBlock((IASTCompoundStatement) body,
- preferences.brace_position_for_block,
- preferences.indent_statements_compare_to_block);
- } finally {
- endOfNode(body);
- }
- } else {
- ok = true;
- scribe.exitAlignment(alignment, true);
- }
- } else {
- ok = true;
- scribe.exitAlignment(alignment, true);
- formatAction(line, body, preferences.brace_position_for_block);
- }
+ ok = true;
} catch (AlignmentException e) {
- if (ok) {
- throw e;
- }
scribe.redoAlignment(e);
}
} while (!ok);
+ scribe.exitAlignment(alignment, true);
+ if (body instanceof IASTCompoundStatement && !startsWithMacroExpansion(body)) {
+// if (body instanceof IASTCompoundStatement && !startsWithMacroExpansion(body)) {
+// formatLeftCurlyBrace(line, preferences.brace_position_for_block);
+// if (startNode(body)) {
+// try {
+// final boolean braceOnSameLine = DefaultCodeFormatterConstants.END_OF_LINE.equals(preferences.brace_position_for_block);
+// if (!braceOnSameLine) {
+// ok = true;
+// scribe.exitAlignment(alignment, true);
+// }
+// formatBlockOpening((IASTCompoundStatement) body,
+// preferences.brace_position_for_block,
+// preferences.insert_space_before_opening_brace_in_block);
+// if (braceOnSameLine) {
+// ok = true;
+// scribe.exitAlignment(alignment, true);
+// }
+// formatOpenedBlock((IASTCompoundStatement) body,
+// preferences.brace_position_for_block,
+// preferences.indent_statements_compare_to_block);
+// } finally {
+// endOfNode(body);
+// }
+// }
+// }
+ if (startNode(body)) {
+ try {
+ if (scribe.scanner.getCurrentPosition() <= body.getFileLocation().getNodeOffset()) {
+ formatLeftCurlyBrace(line, preferences.brace_position_for_block);
+ }
+ formatBlock((IASTCompoundStatement) body,
+ preferences.brace_position_for_block,
+ preferences.insert_space_before_opening_brace_in_block,
+ preferences.indent_statements_compare_to_block);
+ } finally {
+ endOfNode(body);
+ }
+ }
+ } else {
+ formatAction(line, body, preferences.brace_position_for_block);
+ }
+ scribe.printTrailingComment();
return PROCESS_SKIP;
}
@@ -3210,36 +3245,53 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
}
private int visit(IASTIfStatement node) {
- scribe.printNextToken(Token.t_if);
- final int line = scribe.line;
- scribe.printNextToken(Token.tLPAREN, preferences.insert_space_before_opening_paren_in_if);
- if (preferences.insert_space_after_opening_paren_in_if) {
- scribe.space();
+ if (!startsWithMacroExpansion(node)) {
+ scribe.printNextToken(Token.t_if);
+ }
+ final int line = scribe.line;
+ IASTNode condition = node.getConditionExpression();
+ if (condition == null && node instanceof ICPPASTIfStatement) {
+ condition = ((ICPPASTIfStatement) node).getConditionDeclaration();
}
- IASTExpression condExpr= node.getConditionExpression();
final IASTStatement thenStatement = node.getThenClause();
final IASTStatement elseStatement = node.getElseClause();
- Runnable tailFormatter = null;
- if (DefaultCodeFormatterConstants.END_OF_LINE.equals(preferences.brace_position_for_block) &&
- thenStatement instanceof IASTCompoundStatement && !startsWithMacroExpansion(thenStatement)) {
- tailFormatter = new TrailingTokenFormatter(Token.tLBRACE,
- thenStatement.getFileLocation().getNodeOffset(),
- preferences.insert_space_before_opening_brace_in_block, false);
+
+ fExpectSemicolonAfterDeclaration= false;
+ try {
+ if (condition == null || !doNodesHaveSameOffset(node, condition)) {
+ scribe.printNextToken(Token.tLPAREN, preferences.insert_space_before_opening_paren_in_if);
+ if (preferences.insert_space_after_opening_paren_in_if) {
+ scribe.space();
+ }
+ Runnable tailFormatter = null;
+ if (DefaultCodeFormatterConstants.END_OF_LINE.equals(preferences.brace_position_for_block) &&
+ thenStatement instanceof IASTCompoundStatement && !startsWithMacroExpansion(thenStatement)) {
+ tailFormatter = new TrailingTokenFormatter(Token.tLBRACE,
+ thenStatement.getFileLocation().getNodeOffset(),
+ preferences.insert_space_before_opening_brace_in_block, false);
+ }
+ tailFormatter = new ClosingParensesisTailFormatter(
+ preferences.insert_space_before_closing_paren_in_if, tailFormatter);
+ scribe.setTailFormatter(tailFormatter);
+ if (condition == null || condition instanceof IASTProblemHolder) {
+ scribe.skipToToken(Token.tRPAREN);
+ } else {
+ condition.accept(this);
+ }
+ scribe.runTailFormatter();
+ scribe.setTailFormatter(null);
+ } else if (!(condition instanceof IASTProblemHolder)) {
+ condition.accept(this);
+ }
+ } finally {
+ fExpectSemicolonAfterDeclaration= true;
}
- tailFormatter = new ClosingParensesisTailFormatter(
- preferences.insert_space_before_closing_paren_in_if, tailFormatter);
- scribe.setTailFormatter(tailFormatter);
- if (condExpr == null || condExpr instanceof IASTProblemExpression) {
- scribe.skipToToken(Token.tRPAREN);
- } else {
- condExpr.accept(this);
- }
- scribe.runTailFormatter();
- scribe.setTailFormatter(null);
boolean thenStatementIsBlock = false;
if (thenStatement != null) {
- if (thenStatement instanceof IASTCompoundStatement && !startsWithMacroExpansion(thenStatement)) {
+ if (condition != null && doNodeLocationsOverlap(condition, thenStatement)) {
+ thenStatement.accept(this);
+ } else if (thenStatement instanceof IASTCompoundStatement && !startsWithMacroExpansion(thenStatement)) {
final IASTCompoundStatement block = (IASTCompoundStatement) thenStatement;
thenStatementIsBlock = true;
final List statements = Arrays.asList(block.getStatements());
@@ -3263,7 +3315,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
}
}
} else {
- if (node.getFileLocation().getNodeOffset() == thenStatement.getFileLocation().getNodeOffset()) {
+ if (doNodesHaveSameOffset(node, thenStatement)) {
startNode(thenStatement);
}
if (elseStatement == null && preferences.keep_simple_if_on_one_line) {
@@ -3310,34 +3362,38 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
}
if (elseStatement != null) {
- if (peekNextToken() == Token.t_else) {
- if (thenStatementIsBlock) {
- scribe.printNextToken(Token.t_else, preferences.insert_space_after_closing_brace_in_block);
- } else {
- scribe.printNextToken(Token.t_else, true);
- }
- }
-
- if (elseStatement instanceof IASTCompoundStatement && !enclosedInMacroExpansion(elseStatement)) {
- elseStatement.accept(this);
- } else if (elseStatement instanceof IASTIfStatement) {
- if (!preferences.compact_else_if) {
- scribe.startNewLine();
- scribe.indent();
- }
- scribe.space();
- elseStatement.accept(this);
- if (!preferences.compact_else_if) {
- scribe.unIndent();
- }
- } else if (preferences.keep_else_statement_on_same_line) {
- scribe.space();
+ if (condition != null && doNodeLocationsOverlap(condition, elseStatement)) {
elseStatement.accept(this);
} else {
- scribe.startNewLine();
- scribe.indent();
- elseStatement.accept(this);
- scribe.unIndent();
+ if (peekNextToken() == Token.t_else) {
+ if (thenStatementIsBlock) {
+ scribe.printNextToken(Token.t_else, preferences.insert_space_after_closing_brace_in_block);
+ } else {
+ scribe.printNextToken(Token.t_else, true);
+ }
+ }
+
+ if (elseStatement instanceof IASTCompoundStatement && !enclosedInMacroExpansion(elseStatement)) {
+ elseStatement.accept(this);
+ } else if (elseStatement instanceof IASTIfStatement) {
+ if (!preferences.compact_else_if) {
+ scribe.startNewLine();
+ scribe.indent();
+ }
+ scribe.space();
+ elseStatement.accept(this);
+ if (!preferences.compact_else_if) {
+ scribe.unIndent();
+ }
+ } else if (preferences.keep_else_statement_on_same_line) {
+ scribe.space();
+ elseStatement.accept(this);
+ } else {
+ scribe.startNewLine();
+ scribe.indent();
+ elseStatement.accept(this);
+ scribe.unIndent();
+ }
}
}
return PROCESS_SKIP;
@@ -3624,7 +3680,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
scribe.indent();
}
scribe.startNewLine();
-
+
formatClosingBrace(brace_position);
}
} finally {
@@ -3684,9 +3740,9 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
* Test whether the next node location is inside a macro expansion. If it is
* a macro expansion, formatting will be skipped until the next node outside
* the expansion is reached.
- *
+ *
* @param node the AST node to be tested
- * @return false
if the node should be skipped
+ * @return false
if the node should be skipped
*/
private boolean startNode(IASTNode node) {
scribe.startNode();
@@ -3702,7 +3758,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
IASTFileLocation macroLocation = macroExpansion.getFileLocation();
IASTFileLocation nodeLocation = node.getFileLocation();
if (macroLocation.getNodeOffset() >= scribe.scanner.getCurrentPosition() &&
- !scribe.shouldSkip(macroLocation.getNodeOffset()) &&
+ !scribe.shouldSkip(macroLocation.getNodeOffset()) &&
(nodeLocation.getNodeOffset() + nodeLocation.getNodeLength() ==
macroLocation.getNodeOffset() + macroLocation.getNodeLength() ||
locations.length == 2 && isSemicolonLocation(locations[1])) &&
@@ -3729,7 +3785,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
/**
* Formatting of node is complete. Undo skip region if any.
- *
+ *
* @param node
*/
private void endOfNode(IASTNode node) {
@@ -3751,7 +3807,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
/**
* Formatting of node continues after completion of a child node. Establish next skip region.
- *
+ *
* @param node
*/
private void continueNode(IASTNode node) {
@@ -3835,7 +3891,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
/**
* Format an expression nested in parenthesis. If the operand is
* null
, empty parenthesis are expected.
- *
+ *
* @param operand
*/
private void formatParenthesizedExpression(final IASTExpression operand) {
@@ -3944,11 +4000,25 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
return true;
}
+ /**
+ * Returns true if the two given nodes have overlapping file locations. For nodes that are
+ * normally separated by other tokens this is an indication that they were produced by the same
+ * macro expansion.
+ */
private static boolean doNodeLocationsOverlap(IASTNode node1, IASTNode node2) {
IASTFileLocation loc1 = node1.getFileLocation();
IASTFileLocation loc2 = node2.getFileLocation();
return loc1.getNodeOffset() + loc1.getNodeLength() > loc2.getNodeOffset() &&
- loc1.getNodeOffset() < loc2.getNodeOffset() + loc2.getNodeLength();
+ loc1.getNodeOffset() < loc2.getNodeOffset() + loc2.getNodeLength();
+ }
+
+ /**
+ * Returns true if the two given nodes have the same offset. For nodes that are normally
+ * separated by other tokens this is an indication that they were produced by the same macro
+ * expansion.
+ */
+ private static boolean doNodesHaveSameOffset(IASTNode node1, IASTNode node2) {
+ return node1.getFileLocation().getNodeOffset() == node2.getFileLocation().getNodeOffset();
}
private void formatBlock(IASTCompoundStatement block, String block_brace_position,
diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java
index 98bae6602eb..ef207f78c7f 100644
--- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java
+++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java
@@ -963,7 +963,7 @@ public class CodeFormatterTest extends BaseUITestCase {
//M* A::c(M* tm) { N::iterator it = myN.find(tm); if (!it) return NULL; else return *it; }
//void A::a(C e) {
- // if (D::iterator it = m.find (e))
+ // if (D::iterator it = m.find(e))
// m.erase(it);
//}
//T* A::b(T* t) {
@@ -1505,6 +1505,24 @@ public class CodeFormatterTest extends BaseUITestCase {
assertFormatterResult();
}
+ //#define BLOCK { }
+ //#define ALWAYS if(true)
+ //
+ //void foo() {
+ //ALWAYS BLOCK
+ //}
+
+ //#define BLOCK { }
+ //#define ALWAYS if(true)
+ //
+ //void foo() {
+ // ALWAYS
+ // BLOCK
+ //}
+ public void testCompoundStatementAsMacro_Temp() throws Exception {
+ assertFormatterResult();
+ }
+
//#define BLOCK { }
//#define DOIT1() { }
//#define DOIT2() do { } while(false)
@@ -2400,6 +2418,37 @@ public class CodeFormatterTest extends BaseUITestCase {
assertFormatterResult();
}
+ //struct Stream {
+ //Stream& operator <<(const char*);
+ //};
+ //Stream GetStream();
+ //
+ //#define MY_MACRO switch (0) case 0: default: if (bool x = false) ; else GetStream()
+ //
+ //void test() {
+ //MY_MACRO << "Loooooooooooooooooooong string literal" << " another literal.";
+ //MY_MACRO << "Looooooooooooooooooooong string literal" << " another literal.";
+ //}
+
+ //struct Stream {
+ // Stream& operator <<(const char*);
+ //};
+ //Stream GetStream();
+ //
+ //#define MY_MACRO switch (0) case 0: default: if (bool x = false) ; else GetStream()
+ //
+ //void test() {
+ // MY_MACRO << "Loooooooooooooooooooong string literal" << " another literal.";
+ // MY_MACRO << "Looooooooooooooooooooong string literal"
+ // << " another literal.";
+ //}
+ public void testOverloadedLeftShiftChain_6() throws Exception {
+ fOptions.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.SPACE);
+ fOptions.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_OVERLOADED_LEFT_SHIFT_CHAIN,
+ Integer.toString(Alignment.M_COMPACT_SPLIT | Alignment.M_INDENT_ON_COLUMN));
+ assertFormatterResult();
+ }
+
//int main() {
// std::vector> test;
// // some comment