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, * @returnfalse
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: + *+ *
+ * @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); + } + + /** + *- + *
+ * first = null + * second = null + * secondStart = 0 + * secondEnd = 0 + * result => true + *+ *- + *
+ * first = { } + * second = null + * secondStart = 0 + * secondEnd = 0 + * result => false + *+ *- + *
+ * first = { 'a' } + * second = { 'a' } + * secondStart = 0 + * secondEnd = 1 + * result => true + *+ *- + *
+ * first = { 'a' } + * second = { 'A' } + * secondStart = 0 + * secondEnd = 1 + * result => false + *+ *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:
+ *+ *
+ * @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- + *
+ * first = null + * second = null + * secondStart = 0 + * secondEnd = 0 + * isCaseSensitive = false + * result => true + *+ *- + *
+ * first = { } + * second = null + * secondStart = 0 + * secondEnd = 0 + * isCaseSensitive = false + * result => false + *+ *- + *
+ * first = { 'a' } + * second = { 'a' } + * secondStart = 0 + * secondEnd = 1 + * isCaseSensitive = true + * result => true + *+ *- + *
+ * first = { 'a' } + * second = { 'A' } + * secondStart = 0 + * secondEnd = 1 + * isCaseSensitive = true + * result => false + *+ *- + *
+ * first = { 'a' } + * second = { 'A' } + * secondStart = 0 + * secondEnd = 1 + * isCaseSensitive = false + * result => true + *+ *fMasters; +// private final Collection