From 4cff1415976acc0f8f4ff862846c9fea7bcd3fa3 Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Mon, 21 Feb 2011 08:02:03 +0000 Subject: [PATCH] Formatting of line comments. --- .../DefaultCodeFormatterConstants.java | 29 +- .../formatter/CodeFormatterVisitor.java | 30 +- .../DefaultCodeFormatterOptions.java | 236 ++++---- .../cdt/internal/formatter/Scribe.java | 547 ++++++++++++++---- .../internal/formatter/align/Alignment.java | 18 +- .../internal/formatter/scanner/Scanner.java | 22 +- .../cdt/internal/core/CharOperation.java | 184 +++++- .../resources/formatter/sample/Before.cpp | 2 +- .../cdt/ui/tests/text/CodeFormatterTest.java | 41 +- .../formatter/CommentsTabPage.java | 229 ++++++++ .../formatter/FormatterMessages.java | 33 +- .../formatter/FormatterMessages.properties | 19 +- .../formatter/FormatterModifyDialog.java | 4 +- 13 files changed, 1074 insertions(+), 320 deletions(-) create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/CommentsTabPage.java diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterConstants.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterConstants.java index 5f9d2cdfc3d..b22469dbed5 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterConstants.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterConstants.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 QNX Software Systems and others. + * Copyright (c) 2000, 2011 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,7 +7,7 @@ * * Contributors: * QNX Software Systems - Initial API and implementation - * Sergey Prigogin, Google + * Sergey Prigogin (Google) * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.formatter; @@ -497,7 +497,30 @@ public class DefaultCodeFormatterConstants { // * // */ // public final static String FORMATTER_COMMENT_LINE_LENGTH = CCorePlugin.PLUGIN_ID + ".formatter.comment.line_length"; //$NON-NLS-1$ -// + /** + *
+	 * FORMATTER / Option to specify the minimum distance between code and line comment.
+	 *     - option id:         "org.eclipse.cdt.core.formatter.comment.min_distance_between_code_and_line_comment"
+	 *     - possible values:   "<n>", where n is zero or a positive integer
+	 *     - default:           "1"
+	 * 
+ * @since 5.3 + */ + public final static String FORMATTER_COMMENT_MIN_DISTANCE_BETWEEN_CODE_AND_LINE_COMMENT = CCorePlugin.PLUGIN_ID + ".formatter.comment.min_distance_between_code_and_line_comment"; //$NON-NLS-1$ + /** + *
+	 * FORMATTER / Option to control whether the white space between code and line comments should be preserved or replaced with a single space
+	 *     - option id:         "org.eclipse.cdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments"
+	 *     - possible values:   { TRUE, FALSE }
+	 *     - default:           FALSE
+	 * 
+ * @see #TRUE + * @see #FALSE + * @since 5.3 + */ + + public final static String FORMATTER_COMMENT_PRESERVE_WHITE_SPACE_BETWEEN_CODE_AND_LINE_COMMENT = CCorePlugin.PLUGIN_ID + ".formatter.comment.preserve_white_space_between_code_and_line_comments"; //$NON-NLS-1$ + /** *
 	 * FORMATTER / Option to compact else/if
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 b00251060be..65b003f1dfd 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
@@ -368,7 +368,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 		}
 		final int continuationIndentation = preferences.continuation_indentation;
 		Alignment listAlignment = scribe.createAlignment(
-				"macroArguments", //$NON-NLS-1$
+				Alignment.MACRO_ARGUMENTS,
 				preferences.alignment_for_arguments_in_method_invocation,
 				Alignment.R_OUTERMOST,
 				binding.getParameterList().length,
@@ -451,7 +451,9 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 
 	@Override
 	public int visit(IASTDeclaration node) {
-		if (!startNode(node)) { return PROCESS_SKIP; }
+		if (!startNode(node)) {
+			return PROCESS_SKIP;
+		}
 		try {
 			return formatDeclaration(node);
 		} finally {
@@ -1223,7 +1225,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 	private void formatExceptionSpecification(final IASTTypeId[] exceptionSpecification) {
 		if (exceptionSpecification.length > 0) {
 			Alignment alignment =scribe.createAlignment(
-					"exceptionSpecification", //$NON-NLS-1$
+					Alignment.EXCEPTION_SPECIFICATION,
 					preferences.alignment_for_throws_clause_in_method_declaration,
 					exceptionSpecification.length,
 					scribe.scanner.getCurrentPosition());
@@ -1816,7 +1818,8 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 			final int continuationIndentation= align.fContinuationIndentation >= 0 ?
 					align.fContinuationIndentation : preferences.continuation_indentation;
 			Alignment listAlignment = scribe.createAlignment(
-					"listElements_" + (elements.isEmpty() ? "ellipsis" : elements.get(0).getClass().getSimpleName()), //$NON-NLS-1$ //$NON-NLS-2$
+					Alignment.LIST_ELEMENTS_PREFIX +
+							(elements.isEmpty() ? "ellipsis" : elements.get(0).getClass().getSimpleName()), //$NON-NLS-1$
 					align.fMode,
 					align.fTieBreakRule,
 					elementsLength + (addEllipsis ? 1 : 0),
@@ -1956,7 +1959,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 			scribe.space();
 		}
     	Alignment conditionalExpressionAlignment = scribe.createAlignment(
-    			"conditionalExpression", //$NON-NLS-1$
+    			Alignment.CONDITIONAL_EXPRESSION,
     			preferences.alignment_for_conditional_expression,
     			2,
     			scribe.scanner.getCurrentPosition());
@@ -2119,7 +2122,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 		} else {
 			// declaration initializer
 	    	Alignment expressionAlignment= scribe.createAlignment(
-	    			"declarationInitializer", //$NON-NLS-1$
+	    			Alignment.DECLARATION_INITIALIZER,
 	    			preferences.alignment_for_assignment,
 	    			Alignment.R_OUTERMOST,
 	    			1,
@@ -2161,7 +2164,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 		}
 
     	Alignment expressionAlignment= scribe.createAlignment(
-    			"designatedInitializer", //$NON-NLS-1$
+    			Alignment.DESIGNATED_INITIALIZER,
     			preferences.alignment_for_assignment,
     			1,
     			scribe.scanner.getCurrentPosition());
@@ -2307,7 +2310,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 			return formatAssignment(node);
 		}
 		Alignment expressionAlignment= scribe.createAlignment(
-				"binaryExpression", //$NON-NLS-1$
+				Alignment.BINARY_EXPRESSION,
 				preferences.alignment_for_binary_expression,
 				2,
 				scribe.scanner.getCurrentPosition());
@@ -2370,7 +2373,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 		}
 
     	Alignment expressionAlignment= scribe.createAlignment(
-    			"assignmentExpression", //$NON-NLS-1$
+    			Alignment.ASSIGNMENT_EXPRESSION,
     			preferences.alignment_for_assignment,
     			Alignment.R_OUTERMOST,
     			1,
@@ -2454,7 +2457,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 		final IASTName fieldName= node.getFieldName();
 		if (fieldName != null) {
 	    	Alignment alignment= scribe.createAlignment(
-	    			"fieldReference", //$NON-NLS-1$
+	    			Alignment.FIELD_REFERENCE,
 	    			preferences.alignment_for_member_access,
 	    			Alignment.R_OUTERMOST,
 	    			1,
@@ -2677,7 +2680,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 	    scribe.printNextToken(Token.tLPAREN, preferences.insert_space_before_opening_paren_in_for);
 		fInsideFor= true;
 		Alignment alignment = scribe.createAlignment(
-				"for", //$NON-NLS-1$
+				Alignment.FOR,
 				Alignment.M_COMPACT_SPLIT,
 				Alignment.R_OUTERMOST,
 				2,
@@ -2844,7 +2847,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 				}
  				if (elseStatement == null && preferences.keep_simple_if_on_one_line) {
 					Alignment compactIfAlignment = scribe.createAlignment(
-							"compactIf", //$NON-NLS-1$
+							Alignment.COMPACT_IF,
 							preferences.alignment_for_compact_if,
 							Alignment.R_OUTERMOST,
 							1,
@@ -3241,6 +3244,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 	 * @return false if the node should be skipped 
 	 */
 	private boolean startNode(IASTNode node) {
+		scribe.startNode();
 		if (node instanceof IASTProblemHolder) {
 			return false;
 		}
@@ -3610,7 +3614,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
 
 	private boolean commentStartsBlock(int start, int end) {
 		localScanner.resetTo(start, end);
-		if (localScanner.getNextToken() ==  Token.tLBRACE) {
+		if (localScanner.getNextToken() == Token.tLBRACE) {
 			switch (localScanner.getNextToken()) {
 			case Token.tBLOCKCOMMENT:
 			case Token.tLINECOMMENT:
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/DefaultCodeFormatterOptions.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/DefaultCodeFormatterOptions.java
index 9e3f6859538..111374a659f 100644
--- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/DefaultCodeFormatterOptions.java
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/DefaultCodeFormatterOptions.java
@@ -7,9 +7,8 @@
  *
  * Contributors:
  *     IBM Corporation - initial API and implementation
- *     Sergey Prigogin, Google
- *     Anton Leherbauer (Wind River Systems)
  *     Sergey Prigogin (Google)
+ *     Anton Leherbauer (Wind River Systems)
  *******************************************************************************/
 package org.eclipse.cdt.internal.formatter;
 
@@ -81,10 +80,8 @@ public class DefaultCodeFormatterOptions {
 	public String brace_position_for_switch;
 	public String brace_position_for_type_declaration;
 
-	public int continuation_indentation;
-	public int continuation_indentation_for_initializer_list;
-
 //	public int blank_lines_after_includes;
+//	public int blank_lines_at_beginning_of_method_body;
 //	public int blank_lines_before_field;
 //	public int blank_lines_before_first_class_body_declaration;
 //	public int blank_lines_before_includes;
@@ -92,7 +89,6 @@ public class DefaultCodeFormatterOptions {
 //	public int blank_lines_before_method;
 //	public int blank_lines_before_new_chunk;
 //	public int blank_lines_between_type_declarations;
-//	public int blank_lines_at_beginning_of_method_body;
 	
 //	public boolean comment_clear_blank_lines;
 //	public boolean comment_format;
@@ -100,7 +96,13 @@ public class DefaultCodeFormatterOptions {
 //	public boolean comment_format_html;
 //	public boolean comment_format_source;
 //	public int comment_line_length;
+	public int comment_min_distance_between_code_and_line_comment;
+	public boolean comment_preserve_white_space_between_code_and_line_comment;
+	public boolean never_indent_line_comments_on_first_column = true;
 	
+	public int continuation_indentation;
+	public int continuation_indentation_for_initializer_list;
+
 	public boolean indent_statements_compare_to_block;
 	public boolean indent_statements_compare_to_body;
 	public boolean indent_body_declarations_compare_to_access_specifier;
@@ -283,6 +285,15 @@ public class DefaultCodeFormatterOptions {
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_CONSTRUCTOR_INITIALIZER_LIST, getAlignment(this.alignment_for_constructor_initializer_list));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_THROWS_CLAUSE_IN_METHOD_DECLARATION, getAlignment(this.alignment_for_throws_clause_in_method_declaration));
 //		options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGN_TYPE_MEMBERS_ON_COLUMNS, this.align_type_members_on_columns ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
+//		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_AFTER_IMPORTS, Integer.toString(this.blank_lines_after_includes));
+//		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_FIELD, Integer.toString(this.blank_lines_before_field));
+//		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_FIRST_CLASS_BODY_DECLARATION, Integer.toString(this.blank_lines_before_first_class_body_declaration));
+//		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_IMPORTS, Integer.toString(this.blank_lines_before_includes));
+//		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_MEMBER_TYPE, Integer.toString(this.blank_lines_before_member_type));
+//		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_METHOD, Integer.toString(this.blank_lines_before_method));
+//		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_NEW_CHUNK, Integer.toString(this.blank_lines_before_new_chunk));
+//		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BETWEEN_TYPE_DECLARATIONS, Integer.toString(this.blank_lines_between_type_declarations));
+//		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_AT_BEGINNING_OF_METHOD_BODY, Integer.toString(this.blank_lines_at_beginning_of_method_body));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_INITIALIZER_LIST, this.brace_position_for_initializer_list);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_BLOCK, this.brace_position_for_block);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_BLOCK_IN_CASE, this.brace_position_for_block_in_case);
@@ -297,17 +308,10 @@ public class DefaultCodeFormatterOptions {
 //		options.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_HTML, this.comment_format_html ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
 //		options.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_SOURCE, this.comment_format_source ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
 //		options.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_LINE_LENGTH, Integer.toString(this.comment_line_length));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_MIN_DISTANCE_BETWEEN_CODE_AND_LINE_COMMENT, Integer.toString(this.comment_min_distance_between_code_and_line_comment));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_PRESERVE_WHITE_SPACE_BETWEEN_CODE_AND_LINE_COMMENT, this.comment_preserve_white_space_between_code_and_line_comment ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_CONTINUATION_INDENTATION, Integer.toString(this.continuation_indentation));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_CONTINUATION_INDENTATION_FOR_INITIALIZER_LIST, Integer.toString(this.continuation_indentation_for_initializer_list));
-//		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_AFTER_IMPORTS, Integer.toString(this.blank_lines_after_includes));
-//		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_FIELD, Integer.toString(this.blank_lines_before_field));
-//		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_FIRST_CLASS_BODY_DECLARATION, Integer.toString(this.blank_lines_before_first_class_body_declaration));
-//		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_IMPORTS, Integer.toString(this.blank_lines_before_includes));
-//		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_MEMBER_TYPE, Integer.toString(this.blank_lines_before_member_type));
-//		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_METHOD, Integer.toString(this.blank_lines_before_method));
-//		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_NEW_CHUNK, Integer.toString(this.blank_lines_before_new_chunk));
-//		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BETWEEN_TYPE_DECLARATIONS, Integer.toString(this.blank_lines_between_type_declarations));
-//		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_AT_BEGINNING_OF_METHOD_BODY, Integer.toString(this.blank_lines_at_beginning_of_method_body));
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INDENT_STATEMENTS_COMPARE_TO_BLOCK, this.indent_statements_compare_to_block ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INDENT_STATEMENTS_COMPARE_TO_BODY, this.indent_statements_compare_to_body ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_INDENT_BODY_DECLARATIONS_COMPARE_TO_ACCESS_SPECIFIER, this.indent_body_declarations_compare_to_access_specifier ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
@@ -621,90 +625,6 @@ public class DefaultCodeFormatterOptions {
 //		if (alignTypeMembersOnColumnsOption != null) {
 //			this.align_type_members_on_columns = DefaultCodeFormatterConstants.TRUE.equals(alignTypeMembersOnColumnsOption);
 //		}
-		final Object bracePositionForInitializerListOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_INITIALIZER_LIST);
-		if (bracePositionForInitializerListOption != null) {
-			try {
-				this.brace_position_for_initializer_list = (String) bracePositionForInitializerListOption;
-			} catch (ClassCastException e) {
-				this.brace_position_for_initializer_list = DefaultCodeFormatterConstants.END_OF_LINE;
-			}
-		}
-		final Object bracePositionForBlockOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_BLOCK);
-		if (bracePositionForBlockOption != null) {
-			try {
-				this.brace_position_for_block = (String) bracePositionForBlockOption;
-			} catch (ClassCastException e) {
-				this.brace_position_for_block = DefaultCodeFormatterConstants.END_OF_LINE;
-			}
-		}
-		final Object bracePositionForBlockInCaseOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_BLOCK_IN_CASE);
-		if (bracePositionForBlockInCaseOption != null) {
-			try {
-				this.brace_position_for_block_in_case = (String) bracePositionForBlockInCaseOption;
-			} catch (ClassCastException e) {
-				this.brace_position_for_block_in_case = DefaultCodeFormatterConstants.END_OF_LINE;
-			}
-		}
-//		final Object bracePositionForEnumDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_ENUM_DECLARATION);
-//		if (bracePositionForEnumDeclarationOption != null) {
-//			try {
-//				this.brace_position_for_enum_declaration = (String) bracePositionForEnumDeclarationOption;
-//			} catch (ClassCastException e) {
-//				this.brace_position_for_enum_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
-//			}
-//		}
-		final Object bracePositionForMethodDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_METHOD_DECLARATION);
-		if (bracePositionForMethodDeclarationOption != null) {
-			try {
-				this.brace_position_for_method_declaration = (String) bracePositionForMethodDeclarationOption;
-			} catch (ClassCastException e) {
-				this.brace_position_for_method_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
-			}
-		}
-		final Object bracePositionForSwitchOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_SWITCH);
-		if (bracePositionForSwitchOption != null) {
-			try {
-				this.brace_position_for_switch = (String) bracePositionForSwitchOption;
-			} catch (ClassCastException e) {
-				this.brace_position_for_switch = DefaultCodeFormatterConstants.END_OF_LINE;
-			}
-		}
-		final Object bracePositionForTypeDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_TYPE_DECLARATION);
-		if (bracePositionForTypeDeclarationOption != null) {
-			try {
-				this.brace_position_for_type_declaration = (String) bracePositionForTypeDeclarationOption;
-			} catch (ClassCastException e) {
-				this.brace_position_for_type_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
-			}
-		}
-		final Object bracePositionForNamespaceDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_NAMESPACE_DECLARATION);
-		if (bracePositionForNamespaceDeclarationOption != null) {
-			try {
-				this.brace_position_for_namespace_declaration = (String) bracePositionForNamespaceDeclarationOption;
-			} catch (ClassCastException e) {
-				this.brace_position_for_namespace_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
-			}
-		}
-		final Object continuationIndentationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_CONTINUATION_INDENTATION);
-		if (continuationIndentationOption != null) {
-			try {
-				this.continuation_indentation = Integer.parseInt((String) continuationIndentationOption);
-			} catch (NumberFormatException e) {
-				this.continuation_indentation = 2;
-			} catch (ClassCastException e) {
-				this.continuation_indentation = 2;
-			}
-		}
-		final Object continuationIndentationForInitializerListOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_CONTINUATION_INDENTATION_FOR_INITIALIZER_LIST);
-		if (continuationIndentationForInitializerListOption != null) {
-			try {
-				this.continuation_indentation_for_initializer_list = Integer.parseInt((String) continuationIndentationForInitializerListOption);
-			} catch (NumberFormatException e) {
-				this.continuation_indentation_for_initializer_list = 2;
-			} catch (ClassCastException e) {
-				this.continuation_indentation_for_initializer_list = 2;
-			}
-		}
 //		final Object blankLinesAfterIncludesOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_AFTER_IMPORTS);
 //		if (blankLinesAfterIncludesOption != null) {
 //			try {
@@ -795,6 +715,70 @@ public class DefaultCodeFormatterOptions {
 //				this.blank_lines_at_beginning_of_method_body = 0;
 //			}
 //		}
+		final Object bracePositionForInitializerListOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_INITIALIZER_LIST);
+		if (bracePositionForInitializerListOption != null) {
+			try {
+				this.brace_position_for_initializer_list = (String) bracePositionForInitializerListOption;
+			} catch (ClassCastException e) {
+				this.brace_position_for_initializer_list = DefaultCodeFormatterConstants.END_OF_LINE;
+			}
+		}
+		final Object bracePositionForBlockOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_BLOCK);
+		if (bracePositionForBlockOption != null) {
+			try {
+				this.brace_position_for_block = (String) bracePositionForBlockOption;
+			} catch (ClassCastException e) {
+				this.brace_position_for_block = DefaultCodeFormatterConstants.END_OF_LINE;
+			}
+		}
+		final Object bracePositionForBlockInCaseOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_BLOCK_IN_CASE);
+		if (bracePositionForBlockInCaseOption != null) {
+			try {
+				this.brace_position_for_block_in_case = (String) bracePositionForBlockInCaseOption;
+			} catch (ClassCastException e) {
+				this.brace_position_for_block_in_case = DefaultCodeFormatterConstants.END_OF_LINE;
+			}
+		}
+//		final Object bracePositionForEnumDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_ENUM_DECLARATION);
+//		if (bracePositionForEnumDeclarationOption != null) {
+//			try {
+//				this.brace_position_for_enum_declaration = (String) bracePositionForEnumDeclarationOption;
+//			} catch (ClassCastException e) {
+//				this.brace_position_for_enum_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
+//			}
+//		}
+		final Object bracePositionForMethodDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_METHOD_DECLARATION);
+		if (bracePositionForMethodDeclarationOption != null) {
+			try {
+				this.brace_position_for_method_declaration = (String) bracePositionForMethodDeclarationOption;
+			} catch (ClassCastException e) {
+				this.brace_position_for_method_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
+			}
+		}
+		final Object bracePositionForSwitchOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_SWITCH);
+		if (bracePositionForSwitchOption != null) {
+			try {
+				this.brace_position_for_switch = (String) bracePositionForSwitchOption;
+			} catch (ClassCastException e) {
+				this.brace_position_for_switch = DefaultCodeFormatterConstants.END_OF_LINE;
+			}
+		}
+		final Object bracePositionForTypeDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_TYPE_DECLARATION);
+		if (bracePositionForTypeDeclarationOption != null) {
+			try {
+				this.brace_position_for_type_declaration = (String) bracePositionForTypeDeclarationOption;
+			} catch (ClassCastException e) {
+				this.brace_position_for_type_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
+			}
+		}
+		final Object bracePositionForNamespaceDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_NAMESPACE_DECLARATION);
+		if (bracePositionForNamespaceDeclarationOption != null) {
+			try {
+				this.brace_position_for_namespace_declaration = (String) bracePositionForNamespaceDeclarationOption;
+			} catch (ClassCastException e) {
+				this.brace_position_for_namespace_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
+			}
+		}
 //		final Object commentClearBlankLinesOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_COMMENT_CLEAR_BLANK_LINES);
 //		if (commentClearBlankLinesOption != null) {
 //			this.comment_clear_blank_lines = DefaultCodeFormatterConstants.TRUE.equals(commentClearBlankLinesOption);
@@ -825,6 +809,40 @@ public class DefaultCodeFormatterOptions {
 //				this.comment_line_length = 80;
 //			}
 //		}
+		final Object commentMinDistanceBetweenCodeAndLineCommentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_COMMENT_MIN_DISTANCE_BETWEEN_CODE_AND_LINE_COMMENT);
+		if (commentMinDistanceBetweenCodeAndLineCommentOption != null) {
+			try {
+				this.comment_min_distance_between_code_and_line_comment = Integer.parseInt((String) commentMinDistanceBetweenCodeAndLineCommentOption);
+			} catch (NumberFormatException e) {
+				this.comment_min_distance_between_code_and_line_comment = 1;
+			} catch (ClassCastException e) {
+				this.comment_min_distance_between_code_and_line_comment = 1;
+			}
+		}
+		final Object commentPreserveWhiteSpaceBetweenCodeAndLineCommentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_COMMENT_PRESERVE_WHITE_SPACE_BETWEEN_CODE_AND_LINE_COMMENT);
+		if (commentPreserveWhiteSpaceBetweenCodeAndLineCommentOption != null) {
+			this.comment_preserve_white_space_between_code_and_line_comment = DefaultCodeFormatterConstants.TRUE.equals(commentPreserveWhiteSpaceBetweenCodeAndLineCommentOption);
+		}
+		final Object continuationIndentationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_CONTINUATION_INDENTATION);
+		if (continuationIndentationOption != null) {
+			try {
+				this.continuation_indentation = Integer.parseInt((String) continuationIndentationOption);
+			} catch (NumberFormatException e) {
+				this.continuation_indentation = 2;
+			} catch (ClassCastException e) {
+				this.continuation_indentation = 2;
+			}
+		}
+		final Object continuationIndentationForInitializerListOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_CONTINUATION_INDENTATION_FOR_INITIALIZER_LIST);
+		if (continuationIndentationForInitializerListOption != null) {
+			try {
+				this.continuation_indentation_for_initializer_list = Integer.parseInt((String) continuationIndentationForInitializerListOption);
+			} catch (NumberFormatException e) {
+				this.continuation_indentation_for_initializer_list = 2;
+			} catch (ClassCastException e) {
+				this.continuation_indentation_for_initializer_list = 2;
+			}
+		}
 		final Object indentStatementsCompareToBlockOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INDENT_STATEMENTS_COMPARE_TO_BLOCK);
 		if (indentStatementsCompareToBlockOption != null) {
 			this.indent_statements_compare_to_block = DefaultCodeFormatterConstants.TRUE.equals(indentStatementsCompareToBlockOption);
@@ -1463,6 +1481,15 @@ public class DefaultCodeFormatterOptions {
 //		this.alignment_for_selector_in_method_invocation = Alignment.M_COMPACT_SPLIT;
 		this.alignment_for_throws_clause_in_method_declaration = Alignment.M_COMPACT_SPLIT;
 //		this.align_type_members_on_columns = false;
+//		this.blank_lines_after_includes = 1;
+//		this.blank_lines_before_field = 1;
+//		this.blank_lines_before_first_class_body_declaration = 0;
+//		this.blank_lines_before_includes = 1;
+//		this.blank_lines_before_member_type = 1;
+//		this.blank_lines_before_method = 1;
+//		this.blank_lines_before_new_chunk = 1;
+//		this.blank_lines_between_type_declarations = 1;
+//		this.blank_lines_at_beginning_of_method_body = 0;
 		this.brace_position_for_block = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_block_in_case = DefaultCodeFormatterConstants.END_OF_LINE;
 //		this.brace_position_for_enum_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
@@ -1471,6 +1498,8 @@ public class DefaultCodeFormatterOptions {
 		this.brace_position_for_namespace_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_switch = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_type_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
+		this.comment_min_distance_between_code_and_line_comment = 1;
+		this.comment_preserve_white_space_between_code_and_line_comment = false;
 //		this.comment_clear_blank_lines = false;
 //		this.comment_format = true;
 //		this.comment_format_header = false;
@@ -1483,15 +1512,6 @@ public class DefaultCodeFormatterOptions {
 //		this.comment_line_length = 80;
 		this.continuation_indentation = 2;
 		this.continuation_indentation_for_initializer_list = 2;
-//		this.blank_lines_after_includes = 1;
-//		this.blank_lines_before_field = 1;
-//		this.blank_lines_before_first_class_body_declaration = 0;
-//		this.blank_lines_before_includes = 1;
-//		this.blank_lines_before_member_type = 1;
-//		this.blank_lines_before_method = 1;
-//		this.blank_lines_before_new_chunk = 1;
-//		this.blank_lines_between_type_declarations = 1;
-//		this.blank_lines_at_beginning_of_method_body = 0;
 		this.indent_statements_compare_to_block = true;
 		this.indent_statements_compare_to_body = true;
 		this.indent_body_declarations_compare_to_namespace_header = false;
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/Scribe.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/Scribe.java
index b09757a85d0..223d652ffcf 100644
--- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/Scribe.java
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/Scribe.java
@@ -34,6 +34,7 @@ import org.eclipse.text.edits.TextEdit;
  */
 public class Scribe {
 	private static final String EMPTY_STRING= ""; //$NON-NLS-1$
+	private static final char[] EMPTY_CHAR_ARRAY= {};
 	private static final String SPACE= " "; //$NON-NLS-1$
 
 	private static final int INITIAL_SIZE= 100;
@@ -88,6 +89,22 @@ public class Scribe {
 	private int fSkipEndOffset;
 	private int fSkippedIndentations;
 
+	/* Comments formatting */
+	private static final int NO_TRAILING_COMMENT = 0x0000;
+	private static final int BASIC_TRAILING_COMMENT = 0x0100;
+	private int[] lineOffsets;
+	private int numLines;
+
+	// Class to store previous line comment information
+	static class LineComment {
+		boolean contiguous;
+		int currentIndentation;
+		int indentation;
+		int lines;
+		char[] leadingSpaces = EMPTY_CHAR_ARRAY;
+	}
+	final LineComment lastLineComment = new LineComment();
+
 	Scribe(CodeFormatterVisitor formatter, int offset, int length) {
 		scanner= new Scanner();
 		preferences= formatter.preferences;
@@ -113,7 +130,6 @@ public class Scribe {
 
 	private final void addDeleteEdit(int start, int end) {
 		if (edits.length == editsIndex) {
-			// resize
 			resize();
 		}
 		addOptimizedReplaceEdit(start, end - start + 1, EMPTY_STRING);
@@ -121,7 +137,6 @@ public class Scribe {
 
 	public final void addInsertEdit(int insertPosition, CharSequence insertedString) {
 		if (edits.length == editsIndex) {
-			// resize
 			resize();
 		}
 		addOptimizedReplaceEdit(insertPosition, 0, insertedString);
@@ -155,8 +170,8 @@ public class Scribe {
 						edits[editsIndex - 1]= new OptimizedReplaceEdit(previousOffset, previousLength + length,
 								previousReplacement + replacement);
 					} else if (previousLength + length == previousReplacementLength) {
-						// check the characters. If they are identical, we can
-						// get rid of the previous edit
+						// Check the characters. If they are identical,
+						// we can get rid of the previous edit.
 						boolean canBeRemoved= true;
 						loop: for (int i= previousOffset; i < previousOffset + previousReplacementLength; i++) {
 							if (scanner.source[i] != previousReplacement.charAt(i - previousOffset)) {
@@ -203,7 +218,6 @@ public class Scribe {
 	 */
 	public final void addReplaceEdit(int start, int end, String replacement) {
 		if (edits.length == editsIndex) {
-			// resize
 			resize();
 		}
 		addOptimizedReplaceEdit(start, end - start + 1, replacement);
@@ -360,13 +374,57 @@ public class Scribe {
 		return null;
 	}
 
+	private int getIndentationOfOffset(int offset) {
+		int beginningOfLine = getLineStart(offset);
+		int indent = 0;
+		for (int i= beginningOfLine; i < offset; i++) {
+			indent = computeIndentation(scanner.source[i], indent);
+		}
+		return indent;
+	}
+
 	/**
-	 * Answer actual indentation level based on true column position
-	 * 
-	 * @return int
+	 * Computes indentation after applying a character at a given indentation position.
+	 * @param text the text to be applied.
+	 * @param indent the initial indentation.
+	 * @return the resulting indentation.
 	 */
-	public int getColumnIndentationLevel() {
-		return column - 1;
+	private int computeIndentation(char c, int indent) {
+		switch (c) {
+		case '\t':
+			return tabLength > 0 ? indent + tabLength - indent % tabLength : indent;
+		case '\r':
+		case '\n':
+			return 0;
+		default:
+			return indent + 1;
+		}
+	}
+
+	/**
+	 * Computes indentation after applying a given text at a given indentation position.
+	 * @param text the text to be applied.
+	 * @param indent the initial indentation.
+	 * @return the resulting indentation.
+	 */
+	private int computeIndentation(char[] text, int indent) {
+		if (text == null)
+			return indent;
+		int length = text.length;
+		for (int i = 0; i < length; i++) {
+			indent = computeIndentation(text[i], indent);
+		}
+		return indent;
+	}
+
+	private int computeIndentation(CharSequence text, int indent) {
+		if (text == null)
+			return indent;
+		int length = text.length();
+		for (int i = 0; i < length; i++) {
+			indent = computeIndentation(text.charAt(i), indent);
+		}
+		return indent;
 	}
 
 	public String getEmptyLines(int linesNumber) {
@@ -451,8 +509,7 @@ public class Scribe {
 				return indent;
 			}
 			int rem= indent % indentationSize;
-			int addition= rem == 0 ? 0 : indentationSize - rem; // round to
-																// superior
+			int addition= rem == 0 ? 0 : indentationSize - rem; // round to superior
 			return indent + addition;
 		} else {
 			return indent;
@@ -564,6 +621,18 @@ public class Scribe {
 		scannerEndPosition= translationUnitSource.length;
 		scanner.resetTo(0, scannerEndPosition);
 		edits= new OptimizedReplaceEdit[INITIAL_SIZE];
+		// Locate line breaks.
+		lineOffsets = new int[200];
+		numLines = 0;
+		lineOffsets[numLines++] = 0;
+		for (int i = 0; i < translationUnitSource.length; i++) {
+			if (translationUnitSource[i] == '\n') {
+				int len = lineOffsets.length;
+				if (numLines >= len)
+					System.arraycopy(lineOffsets, 0, lineOffsets = new int[len + (len + 1) / 2], 0, len);
+				lineOffsets[numLines++] = i + 1;
+			}
+		}
 	}
 
 	/**
@@ -574,6 +643,31 @@ public class Scribe {
 		skipOverInactive= !list.isEmpty();
 	}
 
+	/**
+	 * Returns offset of the start of the line containing a given offset.
+	 */
+	private int getLineStart(int offset) {
+		// Binary search
+		int down = 0;
+		int up = numLines;
+		while (true) {
+			int mid = (down + up) / 2;
+			int lineOffset = lineOffsets[mid];
+			if (mid == down) {
+				return lineOffset;
+			}
+			if (lineOffset > offset) {
+				up = mid;
+			} else {
+				down = mid;
+			}
+		}
+	}
+
+	private boolean isOnFirstColumn(int offset) {
+		return getLineStart(offset) == offset;
+	}
+
 	private boolean isValidEdit(OptimizedReplaceEdit edit) {
 		final int editLength= edit.length;
 		final int editReplacementLength= edit.replacement.length();
@@ -673,7 +767,7 @@ public class Scribe {
 				}
 				switch (currentToken.type) {
 				case Token.tLBRACE: {
-					scanner.resetTo(scanner.getCurrentTokenStartPosition(), scannerEndPosition-1);
+					scanner.resetTo(scanner.getCurrentTokenStartPosition(), scannerEndPosition - 1);
 					formatOpeningBrace(preferences.brace_position_for_block, preferences.insert_space_before_opening_brace_in_block);
 					if (preferences.indent_statements_compare_to_block) {
 						indent();
@@ -681,7 +775,7 @@ public class Scribe {
 					break;
 				}
 				case Token.tRBRACE: {
-					scanner.resetTo(scanner.getCurrentTokenStartPosition(), scannerEndPosition-1);
+					scanner.resetTo(scanner.getCurrentTokenStartPosition(), scannerEndPosition - 1);
 					if (preferences.indent_statements_compare_to_block) {
 						unIndent();
 					}
@@ -789,7 +883,7 @@ public class Scribe {
 			addInsertEdit(scanner.getCurrentTokenStartPosition(), SPACE);
 		}
 		pendingSpace= false;
-		column+= length;
+		column += length;
 		needSpace= true;
 	}
 
@@ -925,14 +1019,18 @@ public class Scribe {
 		}
 	}
 
+	public boolean printComment() {
+		return printComment(NO_TRAILING_COMMENT);
+	}
+
 	/**
 	 * Prints comment at the current position.
 	 * 
 	 * @return {@code true} if a writespace character was encountered preceding the next token,
 	 */
-	public boolean printComment() {
-		// if we have a space between two tokens we ensure it will be dumped in
-		// the formatted string
+	public boolean printComment(int trailing) {
+		// If we have a space between two tokens we ensure it will be dumped in the formatted
+		// string.
 		int currentTokenStartPosition= scanner.getCurrentPosition();
 		if (shouldSkip(currentTokenStartPosition)) {
 			return false;
@@ -940,7 +1038,8 @@ public class Scribe {
 		boolean hasComment= false;
 		boolean hasLineComment= false;
 		boolean hasWhitespace= false;
-		int count= 0;
+		char[] whiteSpaces= EMPTY_CHAR_ARRAY;
+		int lines= 0;
 		while ((currentToken= scanner.nextToken()) != null) {
 			if (skipOverInactive) {
 				Position inactivePos= getInactivePosAt(scanner.getCurrentTokenStartPosition());
@@ -962,10 +1061,12 @@ public class Scribe {
 					}
 				}
 			}
+			int tokenStartPosition = scanner.getCurrentTokenStartPosition();
 			switch (currentToken.type) {
 			case Token.tWHITESPACE:
-				char[] whiteSpaces= scanner.getCurrentTokenSource();
-				count= 0;
+				whiteSpaces= scanner.getCurrentTokenSource();
+				int whitespacesEndPosition = scanner.getCurrentTokenEndPosition();
+				lines= 0;
 				for (int i= 0, max= whiteSpaces.length; i < max; i++) {
 					switch (whiteSpaces[i]) {
 					case '\r':
@@ -974,88 +1075,172 @@ public class Scribe {
 								i++;
 							}
 						}
-						count++;
+						lines++;
 						break;
 					case '\n':
-						count++;
+						lines++;
 					}
 				}
-				if (count == 0) {
-					hasWhitespace= true;
-					addDeleteEdit(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
-				} else if (hasComment) {
-					if (count == 1) {
-						printNewLine(scanner.getCurrentTokenStartPosition());
-					} else {
-						preserveEmptyLines(count - 1, scanner.getCurrentTokenStartPosition());
+				// If following token is a line comment on the same line or the line just after,
+				// then it might be not really formatted as a trailing comment.
+				boolean realTrailing = trailing != NO_TRAILING_COMMENT;
+				if (realTrailing && scanner.peekNextChar() == '/' && lines == 0) {
+					boolean canChangeTrailing = false;
+					// For basic trailing comment preceded by a line comment, then it depends on
+					// the comments relative position when following comment column (after having
+					// been rounded) is below the preceding one, then it becomes not a good idea
+					// to change the trailing flag.
+					if (trailing == BASIC_TRAILING_COMMENT && hasLineComment) {
+						int currentCommentIndentation = computeIndentation(whiteSpaces, 0);
+						int relativeIndentation = currentCommentIndentation - lastLineComment.currentIndentation;
+						if (tabLength == 0) {
+							canChangeTrailing = relativeIndentation == 0;
+						} else {
+							canChangeTrailing = relativeIndentation > -tabLength;
+						}
 					}
-					addDeleteEdit(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
-				} else if (hasLineComment) {
-					preserveEmptyLines(count - 1, scanner.getCurrentTokenStartPosition());
-					addDeleteEdit(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
-				} else if (count != 0 && (!preferences.join_wrapped_lines || preferences.number_of_empty_lines_to_preserve != 0)) {
-					String preservedEmptyLines= getPreserveEmptyLines(count - 1);
-					addReplaceEdit(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(),
-							preservedEmptyLines);
-					hasWhitespace= preservedEmptyLines.length() == 0;
+					// If the trailing can be changed, then look at the following tokens.
+					if (canChangeTrailing) {
+						int currentTokenPosition = scanner.getCurrentTokenStartPosition();
+						if (scanner.getNextToken() == Token.tLINECOMMENT) {
+							realTrailing = !hasLineComment;
+							switch (scanner.getNextToken()) {
+							case Token.tLINECOMMENT:
+								// At least two contiguous line comments.
+								// The formatter should not consider comments as trailing ones.
+								realTrailing = false;
+								break;
+							case Token.tWHITESPACE:
+								if (scanner.getNextToken() == Token.tLINECOMMENT) {
+									// At least two contiguous line comments.
+									// The formatter should not consider comments as trailing ones.
+									realTrailing = false;
+								}
+								break;
+							}
+						}
+						scanner.resetTo(currentTokenPosition, scanner.eofPosition - 1);
+						scanner.getNextToken(); // Get current token again to restore the scanner state.
+					}
+				}
+				// Strategy to consume spaces and eventually leave at this stage
+				// depends on the fact that a trailing comment is expected or not
+				if (realTrailing) {
+					// If a line comment is consumed, no other comment can be on the same line after
+					if (hasLineComment) {
+						if (lines >= 1) {
+							currentTokenStartPosition = tokenStartPosition;
+							preserveEmptyLines(lines, currentTokenStartPosition);
+							addDeleteEdit(currentTokenStartPosition, whitespacesEndPosition);
+							scanner.resetTo(scanner.getCurrentPosition(), scannerEndPosition - 1);
+							return hasWhitespace;
+						}
+						scanner.resetTo(currentTokenStartPosition, scannerEndPosition - 1);
+						return hasWhitespace;
+					} 
+					// If one or several new lines are consumed, following comments
+					// cannot be considered as trailing ones.
+					if (lines >= 1) {
+						if (hasComment) {
+							printNewLine(tokenStartPosition);
+						}
+						scanner.resetTo(currentTokenStartPosition, scannerEndPosition - 1);
+						return hasWhitespace;
+					}
+					// Delete consumed white spaces
+					hasWhitespace = true;
+					currentTokenStartPosition = scanner.getCurrentPosition();
+					addDeleteEdit(tokenStartPosition, whitespacesEndPosition);
 				} else {
-					addDeleteEdit(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
-					hasWhitespace= true;
+					if (lines == 0) {
+						hasWhitespace= true;
+						addDeleteEdit(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
+					} else if (hasComment) {
+						if (lines == 1) {
+							printNewLine(scanner.getCurrentTokenStartPosition());
+						} else {
+							preserveEmptyLines(lines - 1, scanner.getCurrentTokenStartPosition());
+						}
+						addDeleteEdit(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
+					} else if (hasLineComment) {
+						preserveEmptyLines(lines, scanner.getCurrentTokenStartPosition());
+						addDeleteEdit(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
+					} else if (lines != 0 && (!preferences.join_wrapped_lines || preferences.number_of_empty_lines_to_preserve != 0)) {
+						String preservedEmptyLines= getPreserveEmptyLines(lines - 1);
+						addReplaceEdit(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition(),
+								preservedEmptyLines);
+						hasWhitespace= preservedEmptyLines.length() == 0;
+					} else {
+						addDeleteEdit(scanner.getCurrentTokenStartPosition(), scanner.getCurrentTokenEndPosition());
+						hasWhitespace= true;
+					}
 				}
 				currentTokenStartPosition= scanner.getCurrentPosition();
 				break;
 			case Token.tLINECOMMENT:
-				if (count >= 1) {
-					if (count > 1) {
-						preserveEmptyLines(count - 1, scanner.getCurrentTokenStartPosition());
-					} else if (count == 1) {
+				if (lines >= 1) {
+					if (lines > 1) {
+						preserveEmptyLines(lines - 1, scanner.getCurrentTokenStartPosition());
+					} else if (lines == 1) {
 						printNewLine(scanner.getCurrentTokenStartPosition());
 					}
 				} else if (hasWhitespace) {
-					space();
+					// Look whether comments line may be contiguous or not
+					// Note that when preceding token is a comment line, then only one line
+					// is enough to have an empty line as the line end is included in the comment line.
+					// If comments are contiguous, store the white spaces to be able to compute
+					// the current comment indentation
+					if (lines > 1 || (lines == 1 && hasLineComment)) {
+						lastLineComment.contiguous = false;
+					}
+					lastLineComment.leadingSpaces = whiteSpaces;
+					lastLineComment.lines = lines;
 				}
+				whiteSpaces= EMPTY_CHAR_ARRAY;
 				hasWhitespace= false;
-				printCommentLine();
+				printLineComment();
 				currentTokenStartPosition= scanner.getCurrentPosition();
 				hasLineComment= true;
-				count= 0;
+				lines= 0;
 				break;
 			case Token.tBLOCKCOMMENT:
-				if (count >= 1) {
-					if (count > 1) {
-						preserveEmptyLines(count - 1, scanner.getCurrentTokenStartPosition());
-					} else if (count == 1) {
+				if (lines >= 1) {
+					if (lines > 1) {
+						preserveEmptyLines(lines - 1, scanner.getCurrentTokenStartPosition());
+					} else if (lines == 1) {
 						printNewLine(scanner.getCurrentTokenStartPosition());
 					}
 				} else if (hasWhitespace) {
 					space();
 				}
+				whiteSpaces= EMPTY_CHAR_ARRAY;
 				hasWhitespace= false;
 				printBlockComment(false);
 				currentTokenStartPosition= scanner.getCurrentPosition();
 				hasLineComment= false;
 				hasComment= true;
-				count= 0;
+				lines= 0;
 				break;
 			case Token.tPREPROCESSOR:
 			case Token.tPREPROCESSOR_DEFINE:
 			case Token.tPREPROCESSOR_INCLUDE:
 				if (column != 1)
 					printNewLine(scanner.getCurrentTokenStartPosition());
-				if (count >= 1) {
-					if (count > 1) {
-						preserveEmptyLines(count - 1, scanner.getCurrentTokenStartPosition());
-					} else if (count == 1) {
+				if (lines >= 1) {
+					if (lines > 1) {
+						preserveEmptyLines(lines - 1, scanner.getCurrentTokenStartPosition());
+					} else if (lines == 1) {
 						// printNewLine(scanner.getCurrentTokenStartPosition());
 					}
 				}
+				whiteSpaces= EMPTY_CHAR_ARRAY;
 				hasWhitespace= false;
 				printPreprocessorDirective();
 				printNewLine();
 				currentTokenStartPosition= scanner.getCurrentPosition();
 				hasLineComment= false;
 				hasComment= false;
-				count= 0;
+				lines= 0;
 				break;
 			default:
 				// step back one token
@@ -1080,59 +1265,160 @@ public class Scribe {
 		return null;
 	}
 
-	private void printCommentLine() {
-		int currentTokenStartPosition= scanner.getCurrentTokenStartPosition();
-		int currentTokenEndPosition= scanner.getCurrentTokenEndPosition() + 1;
-		scanner.resetTo(currentTokenStartPosition, currentTokenEndPosition - 1);
-		int currentCharacter;
-		int start= currentTokenStartPosition;
-		int nextCharacterStart= currentTokenStartPosition;
-		printIndentationIfNecessary();
-		if (pendingSpace) {
-			addInsertEdit(currentTokenStartPosition, SPACE);
-		}
-		needSpace= false;
-		pendingSpace= false;
-		int previousStart= currentTokenStartPosition;
+	private void printLineComment() {
+    	int currentTokenStartPosition = scanner.getCurrentTokenStartPosition();
+    	int currentTokenEndPosition = scanner.getCurrentTokenEndPosition() + 1;
+    	scanner.resetTo(currentTokenStartPosition, currentTokenEndPosition - 1);
+    	int currentCharacter;
+    	int start = currentTokenStartPosition;
+    	int nextCharacterStart = currentTokenStartPosition;
 
-		loop: while (nextCharacterStart <= currentTokenEndPosition && (currentCharacter= scanner.getNextChar()) != -1) {
-			nextCharacterStart= scanner.getCurrentPosition();
-
-			switch (currentCharacter) {
-			case '\r':
-				start= previousStart;
-				break loop;
-			case '\n':
-				start= previousStart;
-				break loop;
-			}
-			previousStart= nextCharacterStart;
-		}
-		if (start != currentTokenStartPosition) {
-			addReplaceEdit(start, currentTokenEndPosition - 1, lineSeparator);
-		}
-		line++;
-		column= 1;
-		needSpace= false;
-		pendingSpace= false;
-		lastNumberOfNewLines= 0;
-		scanner.resetTo(currentTokenEndPosition, scannerEndPosition - 1);
-		// realign to the proper value
-		if (currentAlignment != null) {
-			if (memberAlignment != null) {
-				// select the last alignment
-				if (currentAlignment.location.inputOffset > memberAlignment.location.inputOffset) {
-					if (currentAlignment.couldBreak() && currentAlignment.wasSplit) {
-						currentAlignment.performFragmentEffect();
+    	// Print comment line indentation
+    	int commentIndentationLevel;
+   		boolean onFirstColumn = isOnFirstColumn(start);
+    	if (indentationLevel == 0) {
+    		commentIndentationLevel = column - 1;
+    	} else {
+			if (onFirstColumn && preferences.never_indent_line_comments_on_first_column) {
+	   			commentIndentationLevel = column - 1;
+    		} else {
+    			// Indentation may be specific for contiguous comment
+    			// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=293300
+				if (lastLineComment.contiguous) {
+					// The leading spaces have been set while looping in the printComment(int) method
+					int currentCommentIndentation = computeIndentation(lastLineComment.leadingSpaces, 0);
+					// Keep the current comment indentation when over the previous contiguous line comment
+					// and the previous comment has not been re-indented
+					int relativeIndentation = currentCommentIndentation - lastLineComment.currentIndentation;
+					boolean similarCommentsIndentation = false;
+					if (tabLength == 0) {
+						similarCommentsIndentation = relativeIndentation == 0;
+					} else if (relativeIndentation > -tabLength) {
+						similarCommentsIndentation = relativeIndentation == 0
+								|| currentCommentIndentation != 0 && lastLineComment.currentIndentation != 0;
+					}
+					if (similarCommentsIndentation && lastLineComment.indentation != indentationLevel) {
+						int currentIndentationLevel = indentationLevel;
+						indentationLevel = lastLineComment.indentation;
+						printIndentationIfNecessary();
+						indentationLevel = currentIndentationLevel;
+			   			commentIndentationLevel = lastLineComment.indentation;
+					} else {
+						printIndentationIfNecessary();
+			   			commentIndentationLevel = column - 1;
 					}
 				} else {
-					indentationLevel= Math.max(indentationLevel, memberAlignment.breakIndentationLevel);
+	    			printIndentationIfNecessary();
+		   			commentIndentationLevel = column - 1;
+				}
+    		}
+    	}
+    	
+		// Prepare white space before the comment.
+		StringBuilder whitespace = null;
+		if (!lastLineComment.contiguous && commentIndentationLevel != indentationLevel &&
+				!(preferences.never_indent_line_comments_on_first_column && onFirstColumn)) {
+			whitespace = new StringBuilder();
+			int whitespaceStartPosition = currentTokenStartPosition - lastLineComment.leadingSpaces.length;
+			int indent = getIndentationOfOffset(whitespaceStartPosition);
+			int distance = computeIndentation(lastLineComment.leadingSpaces, indent) - indent;
+			if (preferences.comment_preserve_white_space_between_code_and_line_comment &&
+					distance >= preferences.comment_min_distance_between_code_and_line_comment) {
+				whitespace.append(lastLineComment.leadingSpaces);
+			} else {
+				for (int i = 0; i < preferences.comment_min_distance_between_code_and_line_comment; i++) {
+					whitespace.append(' ');
 				}
-			} else if (currentAlignment.couldBreak() && currentAlignment.wasSplit) {
-				currentAlignment.performFragmentEffect();
 			}
 		}
-	}
+
+    	// Store line comment information
+		lastLineComment.currentIndentation = getIndentationOfOffset(currentTokenStartPosition);
+   		lastLineComment.contiguous = true;
+
+		while (true) {
+			Location location = new Location(this, scanner.getCurrentPosition());
+			int commentIndent = commentIndentationLevel;
+
+			// Add pending space if necessary
+			if (whitespace != null) {
+				addInsertEdit(currentTokenStartPosition, whitespace);
+				commentIndent = computeIndentation(whitespace, commentIndentationLevel);
+		    	needSpace = false;
+		    	pendingSpace = false;
+			}
+			lastLineComment.indentation = commentIndent;
+
+	    	int previousStart = currentTokenStartPosition;
+	
+	    	int indent = commentIndent;
+	    	loop: while (nextCharacterStart <= currentTokenEndPosition &&
+	    			(currentCharacter = scanner.getNextChar()) != -1) {
+	    		nextCharacterStart = scanner.getCurrentPosition();
+	
+	    		switch (currentCharacter) {
+				case '\r':
+				case '\n':
+					start = previousStart;
+					break loop;
+	    		}
+	    		indent = computeIndentation((char) currentCharacter, indent);
+	    		previousStart = nextCharacterStart;
+	    	}
+
+	    	if (start != currentTokenStartPosition) {
+	    		// This means that the line comment doesn't end the file
+	    		addReplaceEdit(start, currentTokenEndPosition - 1, lineSeparator);
+	    		line++;
+	    		column = 1;
+	    		lastNumberOfNewLines = 1;
+	    	}
+			if (!checkLineWrapping || indent <= pageWidth || whitespace == null ||
+					commentIndent - commentIndentationLevel <= preferences.comment_min_distance_between_code_and_line_comment) {
+				break;
+			}
+
+			// Maximum line length was exceeded. Try to reduce white space before the comment by
+			// removing the last white space character.
+			whitespace.deleteCharAt(whitespace.length() - 1);
+	    	if (computeIndentation(lastLineComment.leadingSpaces, commentIndentationLevel) - commentIndentationLevel <
+	    			preferences.comment_min_distance_between_code_and_line_comment) {
+	    		// The white space shrank too much. Rebuild it to satisfy the minimum distance
+	    		// requirement.
+	    		whitespace.delete(0, whitespace.length());
+    			for (int i = 0; i < preferences.comment_min_distance_between_code_and_line_comment; i++) {
+					whitespace.append(' ');
+				}
+	    	}
+	    	resetAt(location);
+			scanner.resetTo(location.inputOffset, scanner.eofPosition - 1);
+		}
+
+    	needSpace = false;
+    	pendingSpace = false;
+    	// realign to the proper value
+    	if (currentAlignment != null) {
+    		if (memberAlignment != null) {
+    			// select the last alignment
+    			if (currentAlignment.location.inputOffset > memberAlignment.location.inputOffset) {
+    				if (currentAlignment.couldBreak() && currentAlignment.wasSplit) {
+    					currentAlignment.performFragmentEffect();
+    				}
+    			} else {
+    				indentationLevel = Math.max(indentationLevel, memberAlignment.breakIndentationLevel);
+    			}
+    		} else if (currentAlignment.couldBreak() && currentAlignment.wasSplit) {
+    			currentAlignment.performFragmentEffect();
+    		}
+    		if (currentAlignment.name.equals(Alignment.BINARY_EXPRESSION) &&
+    				currentAlignment.enclosing != null &&
+    				currentAlignment.enclosing.equals(Alignment.BINARY_EXPRESSION) &&
+    				indentationLevel < currentAlignment.breakIndentationLevel) {
+    			indentationLevel = currentAlignment.breakIndentationLevel;
+    		}
+    	}
+    	scanner.resetTo(currentTokenEndPosition, scannerEndPosition - 1);
+    }
 
 	public void printEmptyLines(int linesNumber) {
 		printEmptyLines(linesNumber, scanner.getCurrentTokenEndPosition() + 1);
@@ -1166,9 +1452,7 @@ public class Scribe {
 					if (indentationsAsTab < numberOfLeadingIndents) {
 						buffer.append('\t');
 						indentationsAsTab++;
-						int complement= tabLength - ((column - 1) % tabLength); // amount
-																				// of
-																				// space
+						int complement= tabLength - ((column - 1) % tabLength); // amount of space
 						column+= complement;
 						needSpace= false;
 					} else {
@@ -1178,14 +1462,17 @@ public class Scribe {
 					}
 				}
 			} else {
-				while (column <= indentationLevel) {
+				while (column <= indentationLevel - indentationLevel % tabLength) {
 					buffer.append('\t');
-					int complement= tabLength - ((column - 1) % tabLength); // amount
-																			// of
-																			// space
+					int complement= tabLength - ((column - 1) % tabLength); // amount of space
 					column+= complement;
 					needSpace= false;
 				}
+				while (column <= indentationLevel) {
+					buffer.append(' ');
+					column++;
+					needSpace= false;
+				}
 			}
 			break;
 		case DefaultCodeFormatterOptions.SPACE:
@@ -1246,11 +1533,16 @@ public class Scribe {
 		}
 	}
 
+	public void startNode() {
+		lastLineComment.contiguous = false;
+	}
+
 	public void startNewLine() {
 		if (column > 1) {
 			printNewLine();
 		}
 	}
+
 	public void printNewLine() {
 		printNewLine(scanner.getCurrentTokenEndPosition() + 1);
 	}
@@ -1265,7 +1557,7 @@ public class Scribe {
 			if (!preserveLineBreakIndentation) {
 				column = 1; 
 			}
-			this.preserveLineBreakIndentation = false;
+			preserveLineBreakIndentation = false;
 			return;
 		}
 		addInsertEdit(insertPosition, lineSeparator);
@@ -1275,6 +1567,7 @@ public class Scribe {
 		needSpace= false;
 		pendingSpace= false;
 		preserveLineBreakIndentation = false;
+		lastLineComment.contiguous = false;
 	}
 
 	public void printNextToken(int expectedTokenType) {
@@ -1284,9 +1577,9 @@ public class Scribe {
 	public void printNextToken(int expectedTokenType, boolean considerSpaceIfAny) {
 		// Set brace flag, it's useful for the scribe while preserving line breaks
 		switch (expectedTokenType) {
-			case Token.tRBRACE:
-			case Token.tLBRACE:
-				formatBrace = true;
+		case Token.tRBRACE:
+		case Token.tLBRACE:
+			formatBrace = true;
 		}
 		try {
 			printComment();
@@ -1333,7 +1626,7 @@ public class Scribe {
 				expectations.append(expectedTokenTypes[i]);
 			}
 			throw new AbortFormatting(
-					"["	+ (line + 1) + "/" + column + "] unexpected token type, expecting:[" + expectations.toString() + "], actual:" + currentToken);//$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$
+					"["	+ (line + 1) + "/" + column + "] unexpected token type, expecting:[" + expectations.toString() + "], actual:" + currentToken); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$
 		}
 		print(currentToken.getLength(), considerSpaceIfAny);
 	}
@@ -1368,6 +1661,10 @@ public class Scribe {
 	}
 
 	public void printTrailingComment() {
+		printComment(BASIC_TRAILING_COMMENT);
+	}
+
+	public void printTrailingComment_() {
 		// if we have a space between two tokens we ensure it will be dumped in
 		// the formatted string
 		int currentTokenStartPosition= scanner.getCurrentPosition();
@@ -1423,7 +1720,7 @@ public class Scribe {
 				if (hasWhitespaces) {
 					space();
 				}
-				printCommentLine();
+				printLineComment();
 				currentTokenStartPosition= scanner.getCurrentPosition();
 				hasLineComment= true;
 				break;
@@ -1519,19 +1816,19 @@ public class Scribe {
 	@Override
 	public String toString() {
 		StringBuilder buffer= new StringBuilder();
-		buffer.append("(page width = " + pageWidth + ") - (tabChar = ");//$NON-NLS-1$//$NON-NLS-2$
+		buffer.append("(page width = " + pageWidth + ") - (tabChar = "); //$NON-NLS-1$//$NON-NLS-2$
 		switch (tabChar) {
 		case DefaultCodeFormatterOptions.TAB:
-			buffer.append("TAB");//$NON-NLS-1$
+			buffer.append("TAB"); //$NON-NLS-1$
 			break;
 		case DefaultCodeFormatterOptions.SPACE:
-			buffer.append("SPACE");//$NON-NLS-1$
+			buffer.append("SPACE"); //$NON-NLS-1$
 			break;
 		default:
-			buffer.append("MIXED");//$NON-NLS-1$
+			buffer.append("MIXED"); //$NON-NLS-1$
 		}
 		buffer
-			.append(") - (tabSize = " + tabLength + ")")//$NON-NLS-1$//$NON-NLS-2$
+			.append(") - (tabSize = " + tabLength + ")") //$NON-NLS-1$//$NON-NLS-2$
 			.append(lineSeparator)
 			.append("(line = " + line + ") - (column = " + column + ") - (identationLevel = " + indentationLevel + ")") //$NON-NLS-1$	//$NON-NLS-2$	//$NON-NLS-3$	//$NON-NLS-4$
 			.append(lineSeparator)
@@ -1588,7 +1885,7 @@ public class Scribe {
 				hasComment= true;
 				break;
 			case Token.tLINECOMMENT:
-				printCommentLine();
+				printLineComment();
 				currentTokenStartPosition= scanner.getCurrentPosition();
 				break;
 			case Token.tWHITESPACE:
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/align/Alignment.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/align/Alignment.java
index f6ccfda1ff1..093076c1be8 100644
--- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/align/Alignment.java
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/align/Alignment.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
  *
  * Contributors:
  *     IBM Corporation - initial API and implementation
+ *     Sergey Prigogin (Google)
  *******************************************************************************/
 package org.eclipse.cdt.internal.formatter.align;
 
@@ -19,9 +20,22 @@ import org.eclipse.cdt.internal.formatter.Scribe;
  * @since 4.0
  */
 public class Alignment {
+	// Alignment names.
+	public static final String ASSIGNMENT_EXPRESSION = "assignmentExpression"; //$NON-NLS-1$
+	public static final String BINARY_EXPRESSION = "binaryExpression"; //$NON-NLS-1$
+	public static final String COMPACT_IF = "compactIf"; //$NON-NLS-1$
+	public static final String CONDITIONAL_EXPRESSION = "conditionalExpression"; //$NON-NLS-1$
+	public static final String DECLARATION_INITIALIZER = "declarationInitializer"; //$NON-NLS-1$
+	public static final String DESIGNATED_INITIALIZER = "designatedInitializer"; //$NON-NLS-1$
+	public static final String EXCEPTION_SPECIFICATION = "exceptionSpecification"; //$NON-NLS-1$
+	public static final String FIELD_REFERENCE = "fieldReference"; //$NON-NLS-1$
+	public static final String FOR = "for"; //$NON-NLS-1$
+	public static final String MACRO_ARGUMENTS = "macroArguments"; //$NON-NLS-1$
+	public static final String LIST_ELEMENTS_PREFIX = "listElements_"; //$NON-NLS-1$
+
 	// name of alignment
 	public String name;
-	
+
 	// link to enclosing alignment
 	public Alignment enclosing;
 	 
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/scanner/Scanner.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/scanner/Scanner.java
index 9de9ef78382..c1dd2618711 100644
--- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/scanner/Scanner.java
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/scanner/Scanner.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2008 Wind River Systems, Inc. and others.
+ * Copyright (c) 2006, 2011 Wind River Systems, Inc. and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
  *
  * Contributors:
  *     Anton Leherbauer (Wind River Systems) - initial API and implementation
+ *     Sergey Prigogin (Google)
  *******************************************************************************/
 package org.eclipse.cdt.internal.formatter.scanner;
 
@@ -21,7 +22,6 @@ import org.eclipse.cdt.internal.core.CharOperation;
  * @since 4.0
  */
 public class Scanner extends SimpleScanner {
-
 	public char[] source;
 	public int eofPosition;
 	public int startPosition;
@@ -62,7 +62,7 @@ public class Scanner extends SimpleScanner {
 		if (end >= source.length - 1) {
 			reader= new CharArrayReader(source);
 		} else {
-			reader= new CharArrayReader(source, 0, Math.min(source.length, end+1));
+			reader= new CharArrayReader(source, 0, Math.min(source.length, end + 1));
 		}
 		fContext= new ScannerContext().initialize(reader, start);
 		startPosition= start;
@@ -97,6 +97,13 @@ public class Scanner extends SimpleScanner {
 		return fContext.getOffset() - fContext.undoStackSize();
 	}
 
+	/**
+	 * Returns {@code true} if the scanner has reached the end of file.
+	 */
+	public final boolean atEnd() {
+		return getCurrentPosition() >= eofPosition;
+	}
+
 	/**
 	 * Get the next character.
 	 * @return the next character
@@ -120,6 +127,15 @@ public class Scanner extends SimpleScanner {
 		return false;
 	}
 
+	/**
+	 * Returns the next character without moving the pointer.
+	 */
+	public int peekNextChar() {
+		int c = getChar();
+		ungetChar(c);
+		return c;
+	}
+
 	/**
 	 * Set current scanner offset to given offset.
 	 * 
diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/CharOperation.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/CharOperation.java
index acffdeff81b..730a3dd546d 100644
--- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/CharOperation.java
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/CharOperation.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -8,6 +8,7 @@
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Markus Schorn (Wind River Systems)
+ *     Sergey Prigogin (Google)
  *******************************************************************************/
 package org.eclipse.cdt.internal.core;
 
@@ -17,7 +18,6 @@ package org.eclipse.cdt.internal.core;
  * @since 2.1
  */
 public final class CharOperation {
-
 	/**
 	 * Constant for an empty char array
 	 */
@@ -935,11 +935,13 @@ public final class CharOperation {
 		if (first.length != second.length)
 			return false;
 
-		for (int i = first.length; --i >= 0;)
+		for (int i = first.length; --i >= 0;) {
 			if (!equals(first[i], second[i]))
 				return false;
+		}
 		return true;
 	}
+
 	/**
 	 * If isCaseSensite is true, answers true if the two arrays are identical character
 	 * by character, otherwise false.
@@ -985,11 +987,7 @@ public final class CharOperation {
 	 * @return true if the two arrays are identical character by character according to the value
 	 * of isCaseSensitive, otherwise false
 	 */
-	public static final boolean equals(
-		char[][] first,
-		char[][] second,
-		boolean isCaseSensitive) {
-
+	public static final boolean equals(char[][] first, char[][] second,	boolean isCaseSensitive) {
 		if (isCaseSensitive) {
 			return equals(first, second);
 		}
@@ -1000,9 +998,10 @@ public final class CharOperation {
 		if (first.length != second.length)
 			return false;
 
-		for (int i = first.length; --i >= 0;)
+		for (int i = first.length; --i >= 0;) {
 			if (!equals(first[i], second[i], false))
 				return false;
+		}
 		return true;
 	}
 	/**
@@ -1049,9 +1048,10 @@ public final class CharOperation {
 		if (first.length != second.length)
 			return false;
 
-		for (int i = first.length; --i >= 0;)
+		for (int i = first.length; --i >= 0;) {
 			if (first[i] != second[i])
 				return false;
+		}
 		return true;
 	}
 	/**
@@ -1099,11 +1099,7 @@ public final class CharOperation {
 	 * @return true if the two arrays are identical character by character according to the value
 	 * of isCaseSensitive, otherwise false
 	 */
-	public static final boolean equals(
-		char[] first,
-		char[] second,
-		boolean isCaseSensitive) {
-
+	public static final boolean equals(char[] first, char[] second, boolean isCaseSensitive) {
 		if (isCaseSensitive) {
 			return equals(first, second);
 		}
@@ -1114,12 +1110,147 @@ public final class CharOperation {
 		if (first.length != second.length)
 			return false;
 
-		for (int i = first.length; --i >= 0;)
-			if (Character.toLowerCase(first[i])
-				!= Character.toLowerCase(second[i]))
+		for (int i = first.length; --i >= 0;) {
+			if (Character.toLowerCase(first[i]) != Character.toLowerCase(second[i]))
 				return false;
+		}
 		return true;
 	}
+
+	/**
+	 * Answers true if the first array is identical character by character to a portion of the second array
+	 * delimited from position secondStart (inclusive) to secondEnd(exclusive), otherwise false.
+	 * The equality is case sensitive.
+	 * 
+ *
+ * For example: + *
    + *
  1. +	 *    first = null
    +	 *    second = null
    +	 *    secondStart = 0
    +	 *    secondEnd = 0
    +	 *    result => true
    +	 * 
    + *
  2. + *
  3. +	 *    first = { }
    +	 *    second = null
    +	 *    secondStart = 0
    +	 *    secondEnd = 0
    +	 *    result => false
    +	 * 
    + *
  4. + *
  5. +	 *    first = { 'a' }
    +	 *    second = { 'a' }
    +	 *    secondStart = 0
    +	 *    secondEnd = 1
    +	 *    result => true
    +	 * 
    + *
  6. + *
  7. +	 *    first = { 'a' }
    +	 *    second = { 'A' }
    +	 *    secondStart = 0
    +	 *    secondEnd = 1
    +	 *    result => false
    +	 * 
    + *
  8. + *
+ * @param first the first array + * @param second the second array + * @param secondStart inclusive start position in the second array to compare + * @param secondEnd exclusive end position in the second array to compare + * @return true if the first array is identical character by character to fragment of second array ranging from secondStart to secondEnd-1, otherwise false + * @since 3.0 + */ + public static final boolean equals(char[] first, char[] second, int secondStart, int secondEnd) { + return equals(first, second, secondStart, secondEnd, true); + } + + /** + *

Answers true if the first array is identical character by character to a portion of the second array + * delimited from position secondStart (inclusive) to secondEnd(exclusive), otherwise false. The equality could be either + * case sensitive or case insensitive according to the value of the isCaseSensitive parameter. + *

+ *

For example:

+ *
    + *
  1. +	 *    first = null
    +	 *    second = null
    +	 *    secondStart = 0
    +	 *    secondEnd = 0
    +	 *    isCaseSensitive = false
    +	 *    result => true
    +	 * 
    + *
  2. + *
  3. +	 *    first = { }
    +	 *    second = null
    +	 *    secondStart = 0
    +	 *    secondEnd = 0
    +	 *    isCaseSensitive = false
    +	 *    result => false
    +	 * 
    + *
  4. + *
  5. +	 *    first = { 'a' }
    +	 *    second = { 'a' }
    +	 *    secondStart = 0
    +	 *    secondEnd = 1
    +	 *    isCaseSensitive = true
    +	 *    result => true
    +	 * 
    + *
  6. + *
  7. +	 *    first = { 'a' }
    +	 *    second = { 'A' }
    +	 *    secondStart = 0
    +	 *    secondEnd = 1
    +	 *    isCaseSensitive = true
    +	 *    result => false
    +	 * 
    + *
  8. + *
  9. +	 *    first = { 'a' }
    +	 *    second = { 'A' }
    +	 *    secondStart = 0
    +	 *    secondEnd = 1
    +	 *    isCaseSensitive = false
    +	 *    result => true
    +	 * 
    + *
  10. + *
+ * @param first the first array + * @param second the second array + * @param secondStart inclusive start position in the second array to compare + * @param secondEnd exclusive end position in the second array to compare + * @param isCaseSensitive check whether or not the equality should be case sensitive + * @return true if the first array is identical character by character to fragment of second array ranging from secondStart to secondEnd-1, otherwise false + * @since 3.2 + */ + public static final boolean equals(char[] first, char[] second, int secondStart, int secondEnd, + boolean isCaseSensitive) { + if (first == second) + return true; + if (first == null || second == null) + return false; + if (first.length != secondEnd - secondStart) + return false; + if (isCaseSensitive) { + for (int i = first.length; --i >= 0;) + if (first[i] != second[i + secondStart]) + return false; + } else { + for (int i = first.length; --i >= 0;) { + if (Character.toLowerCase(first[i]) != Character.toLowerCase(second[i + secondStart])) + return false; + } + } + return true; + } + /** * If isCaseSensite is true, the equality is case sensitive, otherwise it is case insensitive. * @@ -1170,12 +1301,8 @@ public final class CharOperation { * value of isCaseSensitive, otherwise false. * @exception NullPointerException if fragment or name is null. */ - public static final boolean fragmentEquals( - char[] fragment, - char[] name, - int startIndex, - boolean isCaseSensitive) { - + public static final boolean fragmentEquals(char[] fragment, char[] name, int startIndex, + boolean isCaseSensitive) { int max = fragment.length; if (name.length < max + startIndex) return false; @@ -1187,14 +1314,13 @@ public final class CharOperation { return false; return true; } - for (int i = max; - --i >= 0; - ) // assumes the prefix is not larger than the name - if (Character.toLowerCase(fragment[i]) - != Character.toLowerCase(name[i + startIndex])) + for (int i = max; --i >= 0;) { // assumes the prefix is not larger than the name + if (Character.toLowerCase(fragment[i]) != Character.toLowerCase(name[i + startIndex])) return false; + } return true; } + /** * Answers a hashcode for the array * diff --git a/core/org.eclipse.cdt.ui.tests/resources/formatter/sample/Before.cpp b/core/org.eclipse.cdt.ui.tests/resources/formatter/sample/Before.cpp index 5a012a8591d..b9dc0b94709 100644 --- a/core/org.eclipse.cdt.ui.tests/resources/formatter/sample/Before.cpp +++ b/core/org.eclipse.cdt.ui.tests/resources/formatter/sample/Before.cpp @@ -55,7 +55,7 @@ const SimpleStruct array[] = void SimpleStruct_construct( struct SimpleStruct * const s ) { -// single line + // single line s->num = 1; s->name = "boo"; s->floatNum = 1.5; 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 e94b77f1cfa..65f9ead673d 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 @@ -126,7 +126,7 @@ public class CodeFormatterTest extends BaseUITestCase { // case CONTINUE_CONFUSION: { // //the indentation problem continues... // } - // default://....still not right + // default: //....still not right // } //} public void testIndentConfusionByCastExpression_Bug191021() throws Exception { @@ -827,6 +827,45 @@ public class CodeFormatterTest extends BaseUITestCase { assertFormatterResult(); } + //void foo() { + // int x; // comment + // int y; // will be shifted to the left to avoid exceeding max line length + // // continuation of the previous comment + //// int z; <- comments starting from the beginning of line are not indented + //} + + //void foo() { + // int x; // comment + // int y; // will be shifted to the left to avoid exceeding max line length + // // continuation of the previous comment + //// int z; <- comments starting from the beginning of line are not indented + //} + public void testLineCommentPreserveWhiteSpaceBefore() throws Exception { + fOptions.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.SPACE); + fOptions.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_PRESERVE_WHITE_SPACE_BETWEEN_CODE_AND_LINE_COMMENT, + DefaultCodeFormatterConstants.TRUE); + assertFormatterResult(); + } + + //void foo() { + // int x; // comment + // int y; // comment + // // continuation of the previous comment + //// int z; <- comments starting from the beginning of line are not indented + //} + + //void foo() { + // int x; // comment + // int y; // comment + // // continuation of the previous comment + //// int z; <- comments starting from the beginning of line are not indented + //} + public void testLineCommentMinDistanceFromCode() throws Exception { + fOptions.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.SPACE); + fOptions.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_MIN_DISTANCE_BETWEEN_CODE_AND_LINE_COMMENT, "2"); + assertFormatterResult(); + } + //void f() { // class Object; // int aVeryLongParameterThatShouldBeInOneLine1; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/CommentsTabPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/CommentsTabPage.java new file mode 100644 index 00000000000..1a7edbf81e7 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/CommentsTabPage.java @@ -0,0 +1,229 @@ +/******************************************************************************* + * Copyright (c) 2000, 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Sergey Prigogin (Google) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.preferences.formatter; + +import java.util.Map; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Group; + +import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants; + +/** + * Tab page for the comment formatter settings. + */ +public class CommentsTabPage extends FormatterTabPage { + +// private static abstract class Controller implements Observer { +// private final Collection fMasters; +// private final Collection fSlaves; +// +// public Controller(Collection masters, Collection slaves) { +// fMasters= masters; +// fSlaves= slaves; +// for (CheckboxPreference pref : fMasters) { +// pref.addObserver(this); +// } +// } +// +// public void update(Observable o, Object arg) { +// boolean enabled= areSlavesEnabled(); +// +// for (Object slave : fSlaves) { +// if (slave instanceof Preference) { +// ((Preference) slave).setEnabled(enabled); +// } else if (slave instanceof Control) { +// ((Group) slave).setEnabled(enabled); +// } +// } +// } +// +// public Collection getMasters() { +// return fMasters; +// } +// +// protected abstract boolean areSlavesEnabled(); +// } +// +// private final static class OrController extends Controller { +// public OrController(Collection masters, Collection slaves) { +// super(masters, slaves); +// update(null, null); +// } +// +// @Override +// protected boolean areSlavesEnabled() { +// for (CheckboxPreference pref : getMasters()) { +// if (pref.getChecked()) +// return true; +// } +// return false; +// } +// } + + private final String PREVIEW= + createPreviewHeader(FormatterMessages.CommentsTabPage_preview_header) + + "void lineComments() {\n" + //$NON-NLS-1$ + "\tprintf(\"%d\\n\", 1234); \t\t// Integer number\n" + //$NON-NLS-1$ + "\tprintf(\"%.5g\\n\", 12.34);\t\t// Floating point number\n" + //$NON-NLS-1$ + "}\n"; //$NON-NLS-1$ + + private TranslationUnitPreview fPreview; + + public CommentsTabPage(ModifyDialog modifyDialog, Map workingValues) { + super(modifyDialog, workingValues); + } + + @Override + protected void doCreatePreferences(Composite composite, int numColumns) { +// final int indent= fPixelConverter.convertWidthInCharsToPixels(4); + + // Global group +// final Group globalGroup= createGroup(numColumns, composite, FormatterMessages.CommentsTabPage_group1_title); +// createPrefFalseTrue(globalGroup, numColumns, FormatterMessages.CommentsTabPage_do_not_join_lines, DefaultCodeFormatterConstants.FORMATTER_JOIN_LINES_IN_COMMENTS, true); + + // Line comment group + final Group lineCommentGroup= createGroup(numColumns, composite, FormatterMessages.CommentsTabPage_group1_title); +// final CheckboxPreference singleLineCommentsOnFirstColumn= createPrefFalseTrue(lineCommentGroup, numColumns, FormatterMessages.CommentsTabPage_format_line_comments_on_first_column, DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_LINE_COMMENT_STARTING_ON_FIRST_COLUMN, false); +// ((GridData) singleLineCommentsOnFirstColumn.getControl().getLayoutData()).horizontalIndent= indent; + createPrefFalseTrue(lineCommentGroup, numColumns, FormatterMessages.CommentsTabPage_preserve_white_space_before_line_comment, DefaultCodeFormatterConstants.FORMATTER_COMMENT_PRESERVE_WHITE_SPACE_BETWEEN_CODE_AND_LINE_COMMENT, false); + createNumberPref(lineCommentGroup, numColumns, FormatterMessages.CommentsTabPage_line_width, DefaultCodeFormatterConstants.FORMATTER_COMMENT_MIN_DISTANCE_BETWEEN_CODE_AND_LINE_COMMENT, 0, 9999); +// final CheckboxPreference singleLineComments= createPrefFalseTrue(lineCommentGroup, numColumns, FormatterMessages.CommentsTabPage_enable_line_comment_formatting, DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_LINE_COMMENT, false); +// createPrefFalseTrue(lineCommentGroup, numColumns, FormatterMessages.CommentsTabPage_never_indent_line_comments_on_first_column, DefaultCodeFormatterConstants.FORMATTER_NEVER_INDENT_LINE_COMMENTS_ON_FIRST_COLUMN, false); + + // Block comment settings +// final Group blockSettingsGroup= createGroup(numColumns, composite, FormatterMessages.CommentsTabPage_group4_title); +// final CheckboxPreference header= createPrefFalseTrue(blockSettingsGroup, numColumns, FormatterMessages.CommentsTabPage_format_header, DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_HEADER, false); +// GridData spacerData= new GridData(0, 0); +// spacerData.horizontalSpan= numColumns; +// final CheckboxPreference blockComment= createPrefFalseTrue(blockSettingsGroup, numColumns, FormatterMessages.CommentsTabPage_enable_block_comment_formatting, DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_BLOCK_COMMENT, false); +// final CheckboxPreference nlBoundariesBlock= createPrefFalseTrue(blockSettingsGroup, numColumns, FormatterMessages.CommentsTabPage_new_lines_at_comment_boundaries, DefaultCodeFormatterConstants.FORMATTER_COMMENT_NEW_LINES_AT_BLOCK_BOUNDARIES, false); +// final CheckboxPreference blankLinesBlock= createPrefFalseTrue(blockSettingsGroup, numColumns, FormatterMessages.CommentsTabPage_remove_blank_block_comment_lines, DefaultCodeFormatterConstants.FORMATTER_COMMENT_CLEAR_BLANK_LINES_IN_BLOCK_COMMENT, false); + + // Doxygen comment formatting settings +// final Group settingsGroup= createGroup(numColumns, composite, FormatterMessages.CommentsTabPage_group2_title); +// final CheckboxPreference doxygen= createPrefFalseTrue(globalGroup, numColumns, FormatterMessages.commentsTabPage_enable_javadoc_comment_formatting, DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_JAVADOC_COMMENT, false); +// final CheckboxPreference html= createPrefFalseTrue(settingsGroup, numColumns, FormatterMessages.CommentsTabPage_format_html, DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_HTML, false); +// final CheckboxPreference code= createPrefFalseTrue(settingsGroup, numColumns, FormatterMessages.CommentsTabPage_format_code_snippets, DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_SOURCE, false); +// final CheckboxPreference blankDoxygen= createPrefInsert(settingsGroup, numColumns, FormatterMessages.CommentsTabPage_blank_line_before_doxygen_tags, DefaultCodeFormatterConstants.FORMATTER_COMMENT_INSERT_EMPTY_LINE_BEFORE_ROOT_TAGS); +// final CheckboxPreference indentDoxygen= createPrefFalseTrue(settingsGroup, numColumns, FormatterMessages.CommentsTabPage_indent_doxygen_tags, DefaultCodeFormatterConstants.FORMATTER_COMMENT_INDENT_ROOT_TAGS, false); +// final CheckboxPreference indentDesc= createPrefFalseTrue(settingsGroup, numColumns, FormatterMessages.CommentsTabPage_indent_description_after_param, DefaultCodeFormatterConstants.FORMATTER_COMMENT_INDENT_PARAMETER_DESCRIPTION, false); +// ((GridData) indentDesc.getControl().getLayoutData()).horizontalIndent= indent; +// final CheckboxPreference nlParam= createPrefInsert(settingsGroup, numColumns, FormatterMessages.CommentsTabPage_new_line_after_param_tags, DefaultCodeFormatterConstants.FORMATTER_COMMENT_INSERT_NEW_LINE_FOR_PARAMETER); +// final CheckboxPreference nlBoundariesDoxygen= createPrefFalseTrue(settingsGroup, numColumns, FormatterMessages.CommentsTabPage_new_lines_at_doxygen_boundaries, DefaultCodeFormatterConstants.FORMATTER_COMMENT_NEW_LINES_AT_JAVADOC_BOUNDARIES, false); +// final CheckboxPreference blankLinesDoxygen= createPrefFalseTrue(settingsGroup, numColumns, FormatterMessages.CommentsTabPage_clear_blank_lines, DefaultCodeFormatterConstants.FORMATTER_COMMENT_CLEAR_BLANK_LINES_IN_JAVADOC_COMMENT, false); + + // Line width settings +// final Group widthGroup= createGroup(numColumns, composite, FormatterMessages.CommentsTabPage_group3_title); +// final NumberPreference lineWidth= createNumberPref(widthGroup, numColumns, FormatterMessages.CommentsTabPage_line_width, DefaultCodeFormatterConstants.FORMATTER_COMMENT_LINE_LENGTH, 0, 9999); + +// ArrayList lineFirstColumnMasters= new ArrayList(); +// lineFirstColumnMasters.add(singleLineComments); +// +// ArrayList lineFirstColumnSlaves= new ArrayList(); +// lineFirstColumnSlaves.add(singleLineCommentsOnFirstColumn); +// +// new Controller(lineFirstColumnMasters, lineFirstColumnSlaves) { +// @Override +// protected boolean areSlavesEnabled() { +// return singleLineComments.getChecked(); +// } +// }.update(null, null); +// +// ArrayList doxygenMaster= new ArrayList(); +// doxygenMaster.add(doxygen); +// doxygenMaster.add(header); +// +// ArrayList doxygenSlaves= new ArrayList(); +// doxygenSlaves.add(settingsGroup); +// doxygenSlaves.add(html); +// doxygenSlaves.add(code); +// doxygenSlaves.add(blankDoxygen); +// doxygenSlaves.add(indentDoxygen); +// doxygenSlaves.add(nlParam); +// doxygenSlaves.add(nlBoundariesDoxygen); +// doxygenSlaves.add(blankLinesDoxygen); +// +// new OrController(doxygenMaster, doxygenSlaves); +// +// ArrayList indentMasters= new ArrayList(); +// indentMasters.add(doxygen); +// indentMasters.add(header); +// indentMasters.add(indentDoxygen); +// +// ArrayList indentSlaves= new ArrayList(); +// indentSlaves.add(indentDesc); +// +// new Controller(indentMasters, indentSlaves) { +// @Override +// protected boolean areSlavesEnabled() { +// return (doxygen.getChecked() || header.getChecked()) && indentDoxygen.getChecked(); +// } +// }.update(null, null); +// +// ArrayList blockMasters= new ArrayList(); +// blockMasters.add(blockComment); +// blockMasters.add(header); +// +// ArrayList blockSlaves= new ArrayList(); +// blockSlaves.add(blockSettingsGroup); +// blockSlaves.add(nlBoundariesBlock); +// blockSlaves.add(blankLinesBlock); +// +// new OrController(blockMasters, blockSlaves); +// +// ArrayList lineWidthMasters= new ArrayList(); +// lineWidthMasters.add(doxygen); +// lineWidthMasters.add(blockComment); +// lineWidthMasters.add(singleLineComments); +// lineWidthMasters.add(header); +// +// ArrayList lineWidthSlaves= new ArrayList(); +// lineWidthSlaves.add(widthGroup); +// lineWidthSlaves.add(lineWidth); +// +// new OrController(lineWidthMasters, lineWidthSlaves); + } + + @Override + protected void initializePage() { + fPreview.setPreviewText(PREVIEW); + } + + /* (non-Javadoc) + * @see org.eclipse.jdt.internal.ui.preferences.formatter.ModifyDialogTabPage#doCreateCPreview(org.eclipse.swt.widgets.Composite) + */ + @Override + protected CPreview doCreateCPreview(Composite parent) { + fPreview= new TranslationUnitPreview(fWorkingValues, parent); + return fPreview; + } + + /* (non-Javadoc) + * @see org.eclipse.jdt.internal.ui.preferences.formatter.ModifyDialogTabPage#doUpdatePreview() + */ + @Override + protected void doUpdatePreview() { + super.doUpdatePreview(); + fPreview.update(); + } + + private CheckboxPreference createPrefFalseTrue(Composite composite, int numColumns, String text, String key, boolean invertPreference) { + if (invertPreference) + return createCheckboxPref(composite, numColumns, text, key, TRUE_FALSE); + return createCheckboxPref(composite, numColumns, text, key, FALSE_TRUE); + } + +// private CheckboxPreference createPrefInsert(Composite composite, int numColumns, String text, String key) { +// return createCheckboxPref(composite, numColumns, text, key, DO_NOT_INSERT_INSERT); +// } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterMessages.java index 60c975508d3..83342075755 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterMessages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterMessages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,7 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation - * Sergey Prigogin, Google + * Sergey Prigogin (Google) * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.preferences.formatter; @@ -19,12 +19,6 @@ import org.eclipse.osgi.util.NLS; */ final class FormatterMessages extends NLS { - private static final String BUNDLE_NAME= FormatterMessages.class.getName(); - - private FormatterMessages() { - // Do not instantiate - } - public static String FormatterTabPage_ShowInvisibleCharacters_label; public static String ModifyDialog_BuiltIn_Status; public static String ModifyDialog_Duplicate_Status; @@ -318,21 +312,14 @@ final class FormatterMessages extends NLS { public static String CodingStyleConfigurationBlock_error_serializing_xml_message; public static String CodingStyleConfigurationBlock_delete_confirmation_title; public static String CodingStyleConfigurationBlock_delete_confirmation_question; + public static String CommentsTabPage_preview_header; + public static String CommentsTabPage_group1_title; + public static String CommentsTabPage_preserve_white_space_before_line_comment; + public static String CommentsTabPage_line_width; public static String CustomCodeFormatterBlock_formatter_name; public static String CustomCodeFormatterBlock_default_formatter; public static String CustomCodeFormatterBlock_formatter_note; public static String CustomCodeFormatterBlock_contributed_formatter_warning; -// public static String CommentsTabPage_group1_title; -// public static String CommentsTabPage_enable_comment_formatting; -// public static String CommentsTabPage_format_header; -// public static String CommentsTabPage_format_html; -// public static String CommentsTabPage_format_code_snippets; -// public static String CommentsTabPage_group2_title; -// public static String CommentsTabPage_clear_blank_lines; -// public static String CommentsTabPage_indent_description_after_param; -// public static String CommentsTabPage_new_line_after_param_tags; -// public static String CommentsTabPage_group3_title; -// public static String CommentsTabPage_line_width; public static String ControlStatementsTabPage_preview_header; public static String ControlStatementsTabPage_general_group_title; public static String ControlStatementsTabPage_general_group_insert_new_line_before_else_statements; @@ -380,7 +367,7 @@ final class FormatterMessages extends NLS { public static String ModifyDialog_tabpage_new_lines_title; public static String ModifyDialog_tabpage_control_statements_title; public static String ModifyDialog_tabpage_line_wrapping_title; -// public static String ModifyDialog_tabpage_comments_title; + public static String ModifyDialog_tabpage_comments_title; public static String ModifyDialogTabPage_preview_label_text; public static String ModifyDialogTabPage_error_msg_values_text_unassigned; public static String ModifyDialogTabPage_error_msg_values_items_text_unassigned; @@ -409,7 +396,11 @@ final class FormatterMessages extends NLS { public static String CPreview_formatter_exception; + private FormatterMessages() { + // Do not instantiate + } + static { - NLS.initializeMessages(BUNDLE_NAME, FormatterMessages.class); + NLS.initializeMessages(FormatterMessages.class.getName(), FormatterMessages.class); } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterMessages.properties index 8bcca30d856..4627de3fb0d 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterMessages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2000, 2008 IBM Corporation and others. +# Copyright (c) 2000, 2011 IBM Corporation and others. # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 # which accompanies this distribution, and is available at @@ -9,7 +9,7 @@ # IBM Corporation - initial API and implementation # istvan@benedek-home.de - 103706 [formatter] indent empty lines # Aaron Luchko, aluchko@redhat.com - 105926 [Formatter] Exporting Unnamed profile fails silently -# Sergey Prigogin, Google +# Sergey Prigogin (Google) # Anton Leherbauer (Wind River Systems) ############################################################################### @@ -67,7 +67,6 @@ WhiteSpaceTabPage_for='for' #WhiteSpaceTabPage_for_before_comma_inc=before comma in increments #WhiteSpaceTabPage_for_after_comma_inc=after comma in increments - WhiteSpaceTabPage_labels=Labels WhiteSpaceTabPage_template_arguments=Template arguments WhiteSpaceTabPage_template_parameters=Template parameters @@ -363,15 +362,11 @@ CustomCodeFormatterBlock_default_formatter=[built-in] CustomCodeFormatterBlock_formatter_note=Note: CustomCodeFormatterBlock_contributed_formatter_warning=Contributed formatters may not respect all code style settings. -#CommentsTabPage_group1_title=General settings -#CommentsTabPage_enable_comment_formatting=Enable &comment formatting -#CommentsTabPage_format_header=Format &header comment -#CommentsTabPage_format_html=Format HTML ta&gs -#CommentsTabPage_format_code_snippets=Format &C code snippets -#CommentsTabPage_clear_blank_lines=Clear &blank lines in comments -#CommentsTabPage_group3_title=Line width -#CommentsTabPage_line_width=Ma&ximum line width for comments: +CommentsTabPage_preview_header=Comments +CommentsTabPage_group1_title=Line comments +CommentsTabPage_preserve_white_space_before_line_comment=Preserve white space between code and line comments if possible +CommentsTabPage_line_width=Minimum distance between code and line comments: ControlStatementsTabPage_preview_header=If...else @@ -431,7 +426,7 @@ ModifyDialog_tabpage_whitespace_title=&White Space ModifyDialog_tabpage_new_lines_title=New &Lines ModifyDialog_tabpage_control_statements_title=Con&trol Statements ModifyDialog_tabpage_line_wrapping_title=Line Wra&pping -#ModifyDialog_tabpage_comments_title=Co&mments +ModifyDialog_tabpage_comments_title=Co&mments ModifyDialog_dialog_title=Profile ''{0}'' ModifyDialog_apply_button=Apply diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterModifyDialog.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterModifyDialog.java index aaa10ad0991..36fe18a7d19 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterModifyDialog.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterModifyDialog.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -33,6 +33,6 @@ public class FormatterModifyDialog extends ModifyDialog { addTabPage(FormatterMessages.ModifyDialog_tabpage_new_lines_title, new NewLinesTabPage(this, values)); addTabPage(FormatterMessages.ModifyDialog_tabpage_control_statements_title, new ControlStatementsTabPage(this, values)); addTabPage(FormatterMessages.ModifyDialog_tabpage_line_wrapping_title, new LineWrappingTabPage(this, values)); -// addTabPage(FormatterMessages.ModifyDialog_tabpage_comments_title, new CommentsTabPage(this, values)); + addTabPage(FormatterMessages.ModifyDialog_tabpage_comments_title, new CommentsTabPage(this, values)); } }