### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: buildnotes_jdt-core.html =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/buildnotes_jdt-core.html,v retrieving revision 1.7343 diff -u -r1.7343 buildnotes_jdt-core.html --- buildnotes_jdt-core.html 2 Mar 2010 12:37:42 -0000 1.7343 +++ buildnotes_jdt-core.html 2 Mar 2010 12:49:51 -0000 @@ -48,6 +48,173 @@
Project org.eclipse.jdt.core v_A38 (cvs).

What's new in this drop

+

Problem Reports Fixed

Index: formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java,v retrieving revision 1.106 diff -u -r1.106 DefaultCodeFormatterConstants.java --- formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java 1 Mar 2010 17:09:32 -0000 1.106 +++ formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java 2 Mar 2010 12:49:53 -0000 @@ -856,6 +856,151 @@ public static final String FORMATTER_CONTINUATION_INDENTATION_FOR_ARRAY_INITIALIZER = JavaCore.PLUGIN_ID + ".formatter.continuation_indentation_for_array_initializer"; //$NON-NLS-1$ /** *
+	 * FORMATTER / Option to define tags used to disable formatting from the beginning of the comment including one of these tags.
+	 *     - option id:         "org.eclipse.jdt.core.formatter.disabling_tags"
+	 *     - default:           null
+	 * 
+ *

+ * Note that: + *

    + *
  1. As soon as the formatter encounter a disabling tag, it stops to format the + * code just after the comment including the tag. If it was already inactive, the + * tag is simply ignored. + *

    Hence, nesting disabling and enabling tags has no specific effect.

    + * For example, in the following snippet: + *
    +	 * class X {
    +	 * // disable-formatter-1
    +	 * void foo1() {}
    +	 * // disable-formatter-2
    +	 * void foo2() {}
    +	 * // enable-formatter-2
    +	 * void bar1() {}
    +	 * // enable-formatter-1
    +	 * void bar2() {}
    +	 * }
    +	 * 
    + * the second disabling tag and the second enabling tag will be ignored by the + * formatter, which will format it the same than: + *
    +	 * class X {
    +	 * // disable-formatter-1
    +	 * void foo1() {}
    +	 * void foo2() {}
    +	 * // enable-formatter-2
    +	 * void bar1() {}
    +	 * void bar2() {}
    +	 * }
    +	 * 
    + *
  2. + *
  3. If no enabling tag is found by the formatter after a disabling tag, then the + * end of the snippet won't be formatted.
    + * For example, to disable the formatting of the entire content of a compilation + * unit, just put a disabling tag at the beginning of the code: + *
    +	 * // disable-formatter
    +	 * class X {
    +	 * void foo1() {}
    +	 * void foo2() {}
    +	 * void bar1() {}
    +	 * void bar2() {}
    +	 * }
    +	 * 
    + * In this case, the formatter will not change the content of the class X. + *
  4. + *
  5. The tag cannot include new line characters but it can have white spaces.
    + * E.g. "format: off" is a valid disabling tag
  6. + *
  7. If a mix of disabling and enabling tags is done in the same comment, then + * the formatter will take into account the last encountered tag in the comment. + *

    For example, in the following snippet, the formatter will be disabled after + * the comment:

    + *
    +	 * class X {
    +	 * /*
    +	 * * This is a comment with a mix of disabling and enabling tags:
    +	 * * disable-formatter-1
    +	 * * enable-formatter-1
    +	 * * disable-formatter-2
    +	 * * The formatter will stop to format after this comment...
    +	 * */
    +	 * void foo() {}
    +	 * void bar() {}
    +	 * }
    +	 * 
    + *
  8. + * + *

    + * @see #FORMATTER_ENABLING_TAGS + * @since 3.6 + */ + public static final String FORMATTER_DISABLING_TAGS = JavaCore.PLUGIN_ID + ".formatter.disabling_tags"; //$NON-NLS-1$ + /** + *
    +	 * FORMATTER / Option to define tags used to enable formatting after the end of the comment including one of these tags.
    +	 *     - option id:         "org.eclipse.jdt.core.formatter.enabling_tags"
    +	 *     - default:           null
    +	 * 
    + *

    + * Note that: + *

      + *
    1. As soon as the formatter encounter an enabling tag, it starts to format + * the code just after the comment including the tag. If it was already active, + * the tag is simply ignored. + *

      Hence, nesting disabling and enabling tags has no specific effect.

      + * For example, in the following snippet: + *
      +	 * class X {
      +	 * // disable-formatter-1
      +	 * void foo1() {}
      +	 * // disable-formatter-2
      +	 * void foo2() {}
      +	 * // enable-formatter-2
      +	 * void bar1() {}
      +	 * // enable-formatter-1
      +	 * void bar2() {}
      +	 * }
      +	 * 
      + * the second disabling tag and the second enabling tag will be ignored by the + * formatter, which will format it the same than: + *
      +	 * class X {
      +	 * // disable-formatter-1
      +	 * void foo1() {}
      +	 * void foo2() {}
      +	 * // enable-formatter-2
      +	 * void bar1() {}
      +	 * void bar2() {}
      +	 * }
      +	 * 
      + *
    2. + *
    3. The tag cannot include new line characters but it can have white spaces.
      + * E.g. "format: on" is a valid enabling tag
    4. + *
    5. If a mix of disabling and enabling tags is done in the same comment, then + * the formatter will take into account the last encountered tag in the comment. + *

      For example, in the following snippet, the formatter will be disabled after + * the comment:

      + *
      +	 * class X {
      +	 * /*
      +	 * * This is a comment with a mix of disabling and enabling tags:
      +	 * * disable-formatter-1
      +	 * * enable-formatter-1
      +	 * * disable-formatter-2
      +	 * * The formatter will stop to format after this comment...
      +	 * */
      +	 * void foo() {}
      +	 * void bar() {}
      +	 * }
      +	 * 
      + *
    6. + *
    + *

    + * @see #FORMATTER_DISABLING_TAGS + * @since 3.6 + */ + public static final String FORMATTER_ENABLING_TAGS = JavaCore.PLUGIN_ID + ".formatter.enabling_tags"; //$NON-NLS-1$ + /** + *
     	 * FORMATTER / Option to indent body declarations compare to its enclosing annotation declaration header
     	 *     - option id:         "org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header"
     	 *     - possible values:   { TRUE, FALSE }
    Index: formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java
    ===================================================================
    RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java,v
    retrieving revision 1.229
    diff -u -r1.229 CodeFormatterVisitor.java
    --- formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java	23 Feb 2010 15:04:52 -0000	1.229
    +++ formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java	2 Mar 2010 12:49:56 -0000
    @@ -756,7 +756,7 @@
     		final char[] compilationUnitSource = string.toCharArray();
     
     		this.localScanner.setSource(compilationUnitSource);
    -		this.scribe.initializeScanner(compilationUnitSource);
    +		this.scribe.resetScanner(compilationUnitSource);
     
     		if (nodes == null) {
     			return null;
    @@ -793,7 +793,7 @@
     		final char[] compilationUnitSource = string.toCharArray();
     
     		this.localScanner.setSource(compilationUnitSource);
    -		this.scribe.initializeScanner(compilationUnitSource);
    +		this.scribe.resetScanner(compilationUnitSource);
     
     		this.lastLocalDeclarationSourceStart = -1;
     		try {
    @@ -822,7 +822,7 @@
     		final char[] compilationUnitSource = string.toCharArray();
     
     		this.localScanner.setSource(compilationUnitSource);
    -		this.scribe.initializeScanner(compilationUnitSource);
    +		this.scribe.resetScanner(compilationUnitSource);
     
     		if (constructorDeclaration == null) {
     			return null;
    @@ -866,7 +866,7 @@
     		final char[] compilationUnitSource = string.toCharArray();
     
     		this.localScanner.setSource(compilationUnitSource);
    -		this.scribe.initializeScanner(compilationUnitSource);
    +		this.scribe.resetScanner(compilationUnitSource);
     
     		if (expression == null) {
     			return null;
    Index: formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
    ===================================================================
    RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java,v
    retrieving revision 1.102
    diff -u -r1.102 DefaultCodeFormatterOptions.java
    --- formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java	1 Mar 2010 17:09:36 -0000	1.102
    +++ formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java	2 Mar 2010 12:49:58 -0000
    @@ -14,8 +14,10 @@
     import java.util.HashMap;
     import java.util.Map;
     
    +import org.eclipse.jdt.core.compiler.CharOperation;
     import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
     import org.eclipse.jdt.core.JavaCore;
    +import org.eclipse.jdt.internal.compiler.util.Util;
     import org.eclipse.jdt.internal.formatter.align.Alignment;
     
     /**
    @@ -116,6 +118,9 @@
     	public boolean comment_insert_new_line_for_parameter;
     	public int comment_line_length;
     
    +	public char[][] disabling_tags;
    +	public char[][] enabling_tags;
    +
     	public boolean indent_statements_compare_to_block;
     	public boolean indent_statements_compare_to_body;
     	public boolean indent_body_declarations_compare_to_annotation_declaration_header;
    @@ -612,6 +617,8 @@
     		options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, Integer.toString(this.tab_size));
     		options.put(DefaultCodeFormatterConstants.FORMATTER_USE_TABS_ONLY_FOR_LEADING_INDENTATIONS, this.use_tabs_only_for_leading_indentations ?  DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
     		options.put(DefaultCodeFormatterConstants.FORMATTER_WRAP_BEFORE_BINARY_OPERATOR, this.wrap_before_binary_operator ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
    +		options.put(DefaultCodeFormatterConstants.FORMATTER_DISABLING_TAGS, this.disabling_tags == null ? Util.EMPTY_STRING : new String(CharOperation.concatWith(this.disabling_tags,',')));
    +		options.put(DefaultCodeFormatterConstants.FORMATTER_ENABLING_TAGS, this.enabling_tags == null ? Util.EMPTY_STRING : new String(CharOperation.concatWith(this.enabling_tags,',')));
     		return options;
     	}
     
    @@ -1949,6 +1956,28 @@
     		if (wrapBeforeBinaryOperatorOption != null) {
     			this.wrap_before_binary_operator = DefaultCodeFormatterConstants.TRUE.equals(wrapBeforeBinaryOperatorOption);
     		}
    +		final Object disableTagsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_DISABLING_TAGS);
    +		if (disableTagsOption != null) {
    +			if (disableTagsOption instanceof String) {
    +				String stringValue = (String) disableTagsOption;
    +				if (stringValue.trim().length() == 0) {
    +					this.disabling_tags = null;
    +				} else {
    +					this.disabling_tags = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
    +				}
    +			}
    +		}
    +		final Object enableTagsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_ENABLING_TAGS);
    +		if (enableTagsOption != null) {
    +			if (enableTagsOption instanceof String) {
    +				String stringValue = (String) enableTagsOption;
    +				if (stringValue.trim().length() == 0) {
    +					this.enabling_tags = null;
    +				} else {
    +					this.enabling_tags = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
    +				}
    +			}
    +		}
     	}
     
     	/**
    Index: formatter/org/eclipse/jdt/internal/formatter/FormatJavadocBlock.java
    ===================================================================
    RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/FormatJavadocBlock.java,v
    retrieving revision 1.12
    diff -u -r1.12 FormatJavadocBlock.java
    --- formatter/org/eclipse/jdt/internal/formatter/FormatJavadocBlock.java	14 Feb 2010 15:57:25 -0000	1.12
    +++ formatter/org/eclipse/jdt/internal/formatter/FormatJavadocBlock.java	2 Mar 2010 12:49:58 -0000
    @@ -358,7 +358,11 @@
     	boolean inlined = (this.flags & INLINED) != 0;
     	if (inlined) buffer.append("	{"); //$NON-NLS-1$
     	buffer.append('@');
    -	buffer.append(TAG_NAMES[this.tagValue]);
    +	if (this.tagValue == TAG_OTHERS_VALUE) {
    +		buffer.append("others_tag"); //$NON-NLS-1$
    +	} else {
    +		buffer.append(TAG_NAMES[this.tagValue]);
    +	}
     	super.toString(buffer);
     	if (this.reference == null) {
     		buffer.append('\n');
    Index: formatter/org/eclipse/jdt/internal/formatter/Scribe.java
    ===================================================================
    RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Scribe.java,v
    retrieving revision 1.195
    diff -u -r1.195 Scribe.java
    --- formatter/org/eclipse/jdt/internal/formatter/Scribe.java	1 Mar 2010 17:09:35 -0000	1.195
    +++ formatter/org/eclipse/jdt/internal/formatter/Scribe.java	2 Mar 2010 12:50:00 -0000
    @@ -78,10 +78,14 @@
     
     	private int[] lineEnds;
     	private int maxLines;
    -	private String lineSeparator;
     	public Alignment memberAlignment;
     	public boolean needSpace = false;
     
    +	// Line separator infos
    +	final private String lineSeparator;
    +	final private char firstLS;
    +	final private int lsLength;
    +
     	public int nlsTagCounter;
     	public int pageWidth;
     	public boolean pendingSpace = false;
    @@ -100,6 +104,9 @@
     	private final boolean indentEmptyLines;
     	int blank_lines_between_import_groups = -1;
     
    +	/** disabling */
    +	boolean editsEnabled = true;
    +
     	/* Comments formatting */
     	private static final int INCLUDE_BLOCK_COMMENTS = CodeFormatter.F_INCLUDE_COMMENTS | CodeFormatter.K_MULTI_LINE_COMMENT;
     	private static final int INCLUDE_JAVA_DOC = CodeFormatter.F_INCLUDE_COMMENTS | CodeFormatter.K_JAVA_DOC;
    @@ -114,6 +121,7 @@
     	private int formatComments = 0;
     	private int headerEndPosition = -1;
     	String commentIndentation; // indentation requested in comments (usually in javadoc root tags description)
    +
     	// Class to store previous line comment information
     	static class LineComment {
     		boolean contiguous = false;
    @@ -123,12 +131,17 @@
     	}
     	final LineComment lastLineComment = new LineComment();
     
    -
     	// New way to format javadoc
     	private FormatterCommentParser formatterCommentParser; // specialized parser to format comments
     
    +	// Disabling and enabling tags
    +	OptimizedReplaceEdit previousDisabledEdit;
    +	private char[][] validationTags;
    +	private int disablingTagsLength;
    +	private int validationTagsLength;
    +
     	Scribe(CodeFormatterVisitor formatter, long sourceLevel, IRegion[] regions, CodeSnippetParsingUtil codeSnippetParsingUtil, boolean includeComments) {
    -		this.scanner = new Scanner(true, true, false/*nls*/, sourceLevel/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
    +		initializeScanner(sourceLevel, formatter.preferences);
     		this.formatter = formatter;
     		this.pageWidth = formatter.preferences.page_width;
     		this.tabLength = formatter.preferences.tab_size;
    @@ -143,6 +156,8 @@
     			this.indentationSize = this.tabLength;
     		}
     		this.lineSeparator = formatter.preferences.line_separator;
    +		this.firstLS = this.lineSeparator.charAt(0);
    +		this.lsLength = this.lineSeparator.length();
     		this.indentationLevel = formatter.preferences.initial_indentation_level * this.indentationSize;
     		this.regions= regions;
     		if (codeSnippetParsingUtil != null) {
    @@ -447,6 +462,18 @@
     	}
     
     	private final void addOptimizedReplaceEdit(int offset, int length, String replacement) {
    +		if (!this.editsEnabled) {
    +			if (this.previousDisabledEdit != null && this.previousDisabledEdit.offset == offset) {
    +				replacement = this.previousDisabledEdit.replacement;
    +			}
    +			this.previousDisabledEdit = null;
    +			if (replacement.indexOf(this.lineSeparator) >= 0) {
    +				if (length == 0 || printNewLinesCharacters(offset, length)) {
    +					this.previousDisabledEdit = new OptimizedReplaceEdit(offset, length, replacement);
    +				}
    +			}
    +			return;
    +		}
     		if (this.editsIndex > 0) {
     			// try to merge last two edits
     			final OptimizedReplaceEdit previous = this.edits[this.editsIndex-1];
    @@ -1269,18 +1296,26 @@
     		this.numberOfIndentations++;
     	}
     
    -	/**
    -	 * @param compilationUnitSource
    -	 */
    -	public void initializeScanner(char[] compilationUnitSource) {
    -		this.scanner.setSource(compilationUnitSource);
    -		this.scannerEndPosition = compilationUnitSource.length;
    -		this.scanner.resetTo(0, this.scannerEndPosition - 1);
    -		this.edits = new OptimizedReplaceEdit[INITIAL_SIZE];
    -		this.maxLines = this.lineEnds == null ? -1 : this.lineEnds.length - 1;
    -		this.scanner.lineEnds = this.lineEnds;
    -		this.scanner.linePtr = this.maxLines;
    -		initFormatterCommentParser();
    +	private void initializeScanner(long sourceLevel, DefaultCodeFormatterOptions preferences) {
    +		char[][] disablingTags = preferences.disabling_tags;
    +		char[][] enablingTags = preferences.enabling_tags;
    +		this.disablingTagsLength = disablingTags == null ? 0 : disablingTags.length;
    +		int eLength = enablingTags == null ? 0 : enablingTags.length;
    +		this.validationTagsLength = this.disablingTagsLength + eLength;
    +		char[][] taskTags = null;
    +		if (this.validationTagsLength > 0) {
    +			this.validationTags = new char[this.validationTagsLength][];
    +			if (this.disablingTagsLength > 0) {
    +				System.arraycopy(disablingTags, 0, this.validationTags, 0, this.disablingTagsLength);
    +			}
    +			if (eLength > 0) {
    +				System.arraycopy(enablingTags, 0, this.validationTags, this.disablingTagsLength, eLength);
    +			}
    +			// copy the task tags array as it will be reordered by the scanner
    +			taskTags = new char[this.validationTagsLength][];
    +			System.arraycopy(this.validationTags, 0, taskTags, 0, this.validationTagsLength);
    +		}
    +		this.scanner = new Scanner(true, true, false/*nls*/, sourceLevel/*sourceLevel*/, taskTags, null/*taskPriorities*/, true/*taskCaseSensitive*/);
     	}
     
     	private void initFormatterCommentParser() {
    @@ -2153,7 +2188,9 @@
     			boolean hasLineComment = false;
     			boolean hasWhitespaces = false;
     			int lines = 0;
    +			int previousFoundTaskCount = this.scanner.foundTaskCount;
     			while ((this.currentToken = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
    +				int foundTaskCount = this.scanner.foundTaskCount;
     				switch(this.currentToken) {
     					case TerminalTokens.TokenNameWHITESPACE :
     						char[] whiteSpaces = this.scanner.getCurrentTokenSource();
    @@ -2279,6 +2316,16 @@
     						currentTokenStartPosition = this.scanner.currentPosition;
     						break;
     					case TerminalTokens.TokenNameCOMMENT_LINE :
    +						if (this.editsEnabled && foundTaskCount > previousFoundTaskCount) {
    +							setEditsEnabled(foundTaskCount, previousFoundTaskCount);
    +							if (!this.editsEnabled && this.editsIndex > 1) {
    +								OptimizedReplaceEdit currentEdit = this.edits[this.editsIndex-1];
    +								if (this.scanner.startPosition == currentEdit.offset+currentEdit.length) {
    +									printNewLinesBeforeDisablingComment();
    +								}
    +							}
    +							previousFoundTaskCount = foundTaskCount;
    +						}
     						if (rejectLineComment) break;
     						if (lines >= 1) {
     							if (lines > 1) {
    @@ -2294,8 +2341,21 @@
     						currentTokenStartPosition = this.scanner.currentPosition;
     						hasLineComment = true;
     						lines = 0;
    +						if (!this.editsEnabled && foundTaskCount > previousFoundTaskCount) {
    +							setEditsEnabled(foundTaskCount, previousFoundTaskCount);
    +						}
     						break;
     					case TerminalTokens.TokenNameCOMMENT_BLOCK :
    +						if (this.editsEnabled && foundTaskCount > previousFoundTaskCount) {
    +							setEditsEnabled(foundTaskCount, previousFoundTaskCount);
    +							if (!this.editsEnabled && this.editsIndex > 1) {
    +								OptimizedReplaceEdit currentEdit = this.edits[this.editsIndex-1];
    +								if (this.scanner.startPosition == currentEdit.offset+currentEdit.length) {
    +									printNewLinesBeforeDisablingComment();
    +								}
    +							}
    +							previousFoundTaskCount = foundTaskCount;
    +						}
     						if (trailing > NO_TRAILING_COMMENT && lines >= 1) {
     							// a block comment on next line means that there's no trailing comment
     							this.scanner.resetTo(this.scanner.getCurrentTokenStartPosition(), this.scannerEndPosition - 1);
    @@ -2318,8 +2378,15 @@
     						hasLineComment = false;
     						hasComment = true;
     						lines = 0;
    +						if (!this.editsEnabled && foundTaskCount > previousFoundTaskCount) {
    +							setEditsEnabled(foundTaskCount, previousFoundTaskCount);
    +						}
     						break;
     					case TerminalTokens.TokenNameCOMMENT_JAVADOC :
    +						if (this.editsEnabled && foundTaskCount > previousFoundTaskCount) {
    +							setEditsEnabled(foundTaskCount, previousFoundTaskCount);
    +							previousFoundTaskCount = foundTaskCount;
    +						}
     						if (trailing > NO_TRAILING_COMMENT) {
     							// a javadoc comment should not be considered as a trailing comment
     							this.scanner.resetTo(this.scanner.getCurrentTokenStartPosition(), this.scannerEndPosition - 1);
    @@ -2342,6 +2409,9 @@
     						} else {
     							printBlockComment(true);
     						}
    +						if (!this.editsEnabled && foundTaskCount > previousFoundTaskCount) {
    +							setEditsEnabled(foundTaskCount, previousFoundTaskCount);
    +						}
     						printNewLine();
     						currentTokenStartPosition = this.scanner.currentPosition;
     						hasLineComment = false;
    @@ -2354,6 +2424,7 @@
     						this.scanner.resetTo(currentTokenStartPosition, this.scannerEndPosition - 1);
     						return;
     				}
    +				previousFoundTaskCount = foundTaskCount;
     			}
     		} catch (InvalidInputException e) {
     			throw new AbortFormatting(e);
    @@ -2363,7 +2434,7 @@
     	void printComment(int kind, String source, int start, int end, int level) {
     
     		// Set scanner
    -		initializeScanner(source.toCharArray());
    +		resetScanner(source.toCharArray());
     		this.scanner.resetTo(start, end);
     		// Put back 3.4RC2 code => comment following line  as it has an impact on Linux tests
     		// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=234336
    @@ -2677,9 +2748,10 @@
     			}
     		}
     
    -		// Delete leading whitespaces if any
    -		if (previousToken != -1 && lastTokenEndPosition != commentStart && spaceEndPosition > lastTokenEndPosition) {
    -			addDeleteEdit(lastTokenEndPosition, spaceEndPosition-1);
    +		// Replace the line separator at the end of the comment if any...
    +		int startReplace = previousToken == SKIP_FIRST_WHITESPACE_TOKEN ? spaceStartPosition : lastTokenEndPosition;
    +		if (this.column == 1 && commentEnd >= startReplace) {
    +			addReplaceEdit(startReplace, commentEnd, this.formatter.preferences.line_separator);
     		}
     	}
     
    @@ -4319,6 +4391,135 @@
     		this.lastLineComment.contiguous = false;
     	}
     
    +	/*
    +	 * Print the indentation of a disabling comment
    +	 */
    +	private void printNewLinesBeforeDisablingComment() {
    +
    +		// Get the beginning of comment line
    +		int linePtr = Arrays.binarySearch(this.lineEnds, this.scanner.startPosition);
    +		if (linePtr < 0) {
    +			linePtr = -linePtr - 1;
    +		}
    +		int indentation = 0;
    +		int beginningOfLine = getLineEnd(linePtr)+1;
    +		if (beginningOfLine == -1) {
    +			beginningOfLine = 0;
    +		}
    +		
    +		// If the comment is in the middle of the line, then there's nothing to do
    +		OptimizedReplaceEdit currentEdit = this.edits[this.editsIndex-1];
    +		int offset = currentEdit.offset;
    +		if (offset >= beginningOfLine) return;
    +
    +		// Compute the comment indentation
    +		int scannerStartPosition = this.scanner.startPosition;
    +		int scannerEofPosition = this.scanner.eofPosition;
    +		int scannerCurrentPosition = this.scanner.currentPosition;
    +		char scannerCurrentChar = this.scanner.currentCharacter;
    +		int length = currentEdit.length;
    +		this.scanner.resetTo(beginningOfLine, offset+length-1);
    +		try {
    +			while (!this.scanner.atEnd()) {
    +				char ch = (char) this.scanner.getNextChar();
    +				switch (ch) {
    +					case '\t' :
    +						if (this.tabLength != 0) {
    +							int reminder = indentation % this.tabLength;
    +							if (reminder == 0) {
    +								indentation += this.tabLength;
    +							} else {
    +								indentation = ((indentation / this.tabLength) + 1) * this.tabLength;
    +							}
    +						}
    +						break;
    +					case ' ':
    +						indentation++;
    +						break;
    +					default:
    +						// Should not happen as the offset of the edit is before the beginning of line
    +						return;
    +				}
    +			}
    +		
    +			// Split the existing edit to keep the change before the beginning of the last line
    +			// but change the indentation after. Note that at this stage, the add*Edit methods
    +			// cannot be longer used as the edits are disabled
    +			StringBuffer indentationBuffer = new StringBuffer();
    +			int currentIndentation = getCurrentIndentation(this.scanner.currentPosition);
    +			if (currentIndentation > 0 && this.indentationLevel > 0) {
    +				int col = this.column;
    +				printIndentationIfNecessary(indentationBuffer);
    +				this.column = col;
    +			}
    +			String replacement = currentEdit.replacement;
    +			if (replacement.length() == 0) {
    +				// previous edit was a delete, as we're sure to have a new line before
    +				// the comment, then the edit needs to be either replaced entirely with
    +				// the expected indentation
    +				this.edits[this.editsIndex-1] = new OptimizedReplaceEdit(beginningOfLine, offset+length-beginningOfLine, indentationBuffer.toString());
    +			} else {
    +				int idx = replacement.lastIndexOf(this.lineSeparator);
    +				if (idx >= 0) {
    +					// replace current edit if it contains a line separator
    +					int start = idx + this.lsLength;
    +					StringBuffer buffer = new StringBuffer(replacement.substring(0, start));
    +					buffer.append(indentationBuffer);
    +					this.edits[this.editsIndex-1] = new OptimizedReplaceEdit(offset, length, buffer.toString());
    +				}
    +			}
    +		}
    +		finally {
    +			this.scanner.startPosition = scannerStartPosition;
    +			this.scanner.eofPosition = scannerEofPosition;
    +			this.scanner.currentPosition = scannerCurrentPosition;
    +			this.scanner.currentCharacter = scannerCurrentChar;
    +		}
    +	}
    +
    +	/*
    +	 * Print new lines characters when the edits are disabled. In this case, only
    +	 * the line separator is replaced if necessary, the other white spaces are untouched.
    +	 */
    +	private boolean printNewLinesCharacters(int offset, int length) {
    +		boolean foundNewLine = false;
    +		int scannerStartPosition = this.scanner.startPosition;
    +		int scannerEofPosition = this.scanner.eofPosition;
    +		int scannerCurrentPosition = this.scanner.currentPosition;
    +		char scannerCurrentChar = this.scanner.currentCharacter;
    +		this.scanner.resetTo(offset, offset+length-1);
    +		try {
    +			while (!this.scanner.atEnd()) {
    +				int start = this.scanner.currentPosition;
    +				char ch = (char) this.scanner.getNextChar();
    +				boolean needReplace = ch != this.firstLS;
    +				switch (ch) {
    +					case '\r':
    +						if (this.scanner.atEnd()) break;
    +						ch = (char) this.scanner.getNextChar();
    +						if (ch != '\n') break;
    +						needReplace = needReplace || this.lsLength != 2;
    +						//$FALL-THROUGH$
    +					case '\n':
    +						if (needReplace) {
    +							if (this.editsIndex == 0 || this.edits[this.editsIndex-1].offset != start) {
    +								this.edits[this.editsIndex++] = new OptimizedReplaceEdit(start, this.scanner.currentPosition-start, this.lineSeparator);
    +							}
    +						}
    +						foundNewLine = true;
    +						break;
    +				}
    +			}
    +		}
    +		finally {
    +			this.scanner.startPosition = scannerStartPosition;
    +			this.scanner.eofPosition = scannerEofPosition;
    +			this.scanner.currentPosition = scannerCurrentPosition;
    +			this.scanner.currentCharacter = scannerCurrentChar;
    +		}
    +		return foundNewLine;		
    +	}
    +
     	public void printNextToken(int expectedTokenType){
     		printNextToken(expectedTokenType, false);
     	}
    @@ -4526,10 +4727,41 @@
     		this.formatter.lastLocalDeclarationSourceStart = location.lastLocalDeclarationSourceStart;
     	}
     
    +	/**
    +	 * @param compilationUnitSource
    +	 */
    +	public void resetScanner(char[] compilationUnitSource) {
    +		this.scanner.setSource(compilationUnitSource);
    +		this.scannerEndPosition = compilationUnitSource.length;
    +		this.scanner.resetTo(0, this.scannerEndPosition - 1);
    +		this.edits = new OptimizedReplaceEdit[INITIAL_SIZE];
    +		this.maxLines = this.lineEnds == null ? -1 : this.lineEnds.length - 1;
    +		this.scanner.lineEnds = this.lineEnds;
    +		this.scanner.linePtr = this.maxLines;
    +		initFormatterCommentParser();
    +	}
    +
     	private void resize() {
     		System.arraycopy(this.edits, 0, (this.edits = new OptimizedReplaceEdit[this.editsIndex * 2]), 0, this.editsIndex);
     	}
     
    +	/*
    +	 * Look for the tags identified by the scanner to see whether some of them
    +	 * may change the status of the edition for the formatter.
    +	 */
    +	private void setEditsEnabled(int count, int previous) {
    +		for (int i=previous; i= this.disablingTagsLength;
    +					// do not return yet, as there may have several disabling/enabling
    +					// tags in a comment, hence the last one will be the one really
    +					// changing the formatter behavior...
    +				}
    +			}
    +		}
    +	}
    +
     	void setIncludeComments(boolean on) {
     		if (on) {
     			this.formatComments |= CodeFormatter.F_INCLUDE_COMMENTS;
    #P org.eclipse.jdt.core.tests.model
    Index: src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
    ===================================================================
    RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java,v
    retrieving revision 1.23
    diff -u -r1.23 FormatterBugsTests.java
    --- src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java	23 Feb 2010 15:00:54 -0000	1.23
    +++ src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java	2 Mar 2010 12:50:04 -0000
    @@ -15,6 +15,7 @@
     import junit.framework.Test;
     
     import org.eclipse.jdt.core.JavaModelException;
    +import org.eclipse.jdt.core.formatter.CodeFormatter;
     import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
     import org.eclipse.jdt.core.formatter.IndentManipulation;
     import org.eclipse.jdt.internal.formatter.DefaultCodeFormatter;
    @@ -66,6 +67,573 @@
     }
     
     /**
    + * @bug 27079: [formatter] Tags for disabling/enabling code formatter (feature)
    + * @test Ensure that the formatter does not format code between specific javadoc comments
    + * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=27079"
    + */
    +public void testBug027079a() throws JavaModelException {
    +	String source =
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"/* disable-formatter */\n" + 
    +		"void     foo(    )      {	\n" + 
    +		"				//      unformatted       comment\n" + 
    +		"}\n" + 
    +		"/* enable-formatter */\n" + 
    +		"void     bar(    )      {	\n" + 
    +		"				//      formatted       comment\n" + 
    +		"}\n" + 
    +		"}\n";
    +	formatSource(source,
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"	/* disable-formatter */\n" + 
    +		"	void foo() {\n" + 
    +		"		// unformatted comment\n" + 
    +		"	}\n" + 
    +		"\n" + 
    +		"	/* enable-formatter */\n" + 
    +		"	void bar() {\n" + 
    +		"		// formatted comment\n" + 
    +		"	}\n" + 
    +		"}\n"
    +	);
    +}
    +public void testBug027079a1() throws JavaModelException {
    +	this.formatterPrefs.disabling_tags = new char[][] { "disable-formatter".toCharArray() };
    +	this.formatterPrefs.enabling_tags = new char[][] { "enable-formatter".toCharArray() };
    +	String source =
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"/* disable-formatter */\n" + 
    +		"void     foo(    )      {	\n" + 
    +		"				//      unformatted       comment\n" + 
    +		"}\n" + 
    +		"/* enable-formatter */\n" + 
    +		"void     bar(    )      {	\n" + 
    +		"				//      formatted       comment\n" + 
    +		"}\n" + 
    +		"}\n";
    +	formatSource(source,
    +		"public class X {\n" + 
    +		"\n" + 
    +		"/* disable-formatter */\n" + 
    +		"void     foo(    )      {	\n" + 
    +		"				//      unformatted       comment\n" + 
    +		"}\n" + 
    +		"/* enable-formatter */\n" + 
    +		"	void bar() {\n" + 
    +		"		// formatted comment\n" + 
    +		"	}\n" + 
    +		"}\n"
    +	);
    +}
    +public void testBug027079a2() throws JavaModelException {
    +	this.formatterPrefs.disabling_tags = new char[][] { "disable-formatter".toCharArray() };
    +	this.formatterPrefs.enabling_tags = new char[][] { "enable-formatter".toCharArray() };
    +	String source =
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"/** disable-formatter */\n" + 
    +		"void     foo(    )      {	\n" + 
    +		"				//      unformatted       comment\n" + 
    +		"}\n" + 
    +		"/** enable-formatter */\n" + 
    +		"void     bar(    )      {	\n" + 
    +		"				//      formatted       comment\n" + 
    +		"}\n" + 
    +		"}\n";
    +	formatSource(source,
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"/** disable-formatter */\n" + 
    +		"void     foo(    )      {	\n" + 
    +		"				//      unformatted       comment\n" + 
    +		"}\n" + 
    +		"/** enable-formatter */\n" + 
    +		"	void bar() {\n" + 
    +		"		// formatted comment\n" + 
    +		"	}\n" + 
    +		"}\n"
    +	);
    +}
    +public void testBug027079a3() throws JavaModelException {
    +	this.formatterPrefs.disabling_tags = new char[][] { "disable-formatter".toCharArray() };
    +	this.formatterPrefs.enabling_tags = new char[][] { "enable-formatter".toCharArray() };
    +	String source =
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"// disable-formatter\n" + 
    +		"void     foo(    )      {	\n" + 
    +		"				//      unformatted       comment\n" + 
    +		"}\n" + 
    +		"// enable-formatter\n" + 
    +		"void     bar(    )      {	\n" + 
    +		"				//      formatted       comment\n" + 
    +		"}\n" + 
    +		"}\n";
    +	formatSource(source,
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"// disable-formatter\n" + 
    +		"void     foo(    )      {	\n" + 
    +		"				//      unformatted       comment\n" + 
    +		"}\n" + 
    +		"// enable-formatter\n" + 
    +		"	void bar() {\n" + 
    +		"		// formatted comment\n" + 
    +		"	}\n" + 
    +		"}\n"
    +	);
    +}
    +public void testBug027079a4() throws JavaModelException {
    +	this.formatterPrefs.disabling_tags = new char[][] { "disable-formatter".toCharArray() };
    +	this.formatterPrefs.enabling_tags = new char[][] { "enable-formatter".toCharArray() };
    +	String source =
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"// disable-formatter\n" + 
    +		"void     foo(    )      {	\n" + 
    +		"				//      unformatted       comment  	  \n" + 
    +		"}\n" + 
    +		"// enable-formatter \n" + 
    +		"void     bar(    )      {	\n" + 
    +		"				//      formatted       comment  	  \n" + 
    +		"				/* disable-formatter *//*      unformatted		comment  	  *//* enable-formatter */\n" + 
    +		"}\n" + 		"}\n";
    +	formatSource(source,
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"// disable-formatter\n" + 
    +		"void     foo(    )      {	\n" + 
    +		"				//      unformatted       comment  	  \n" + 
    +		"}\n" + 
    +		"// enable-formatter \n" + 
    +		"	void bar() {\n" + 
    +		"		// formatted comment\n" + 
    +		"		/* disable-formatter *//*      unformatted		comment  	  *//* enable-formatter */\n" + 
    +		"	}\n" + 
    +		"}\n"
    +	);
    +}
    +public void testBug027079b() throws JavaModelException {
    +	this.formatterPrefs.disabling_tags = new char[][] { "disable-formatter".toCharArray() };
    +	this.formatterPrefs.enabling_tags = new char[][] { "enable-formatter".toCharArray() };
    +	String source =
    +		"public class X02 {\n" + 
    +		"void foo() {\n" + 
    +		"/* disable-formatter */\n" + 
    +		"				/*       unformatted		comment  	  */\n" + 
    +		"	String test1= \"this\"+\n" + 
    +		"					\"is\"+\n" + 
    +		"			\"a specific\"+\n" + 
    +		"		\"line wrapping \";\n" + 
    +		"\n" + 
    +		"/* enable-formatter */\n" + 
    +		"				/*       formatted		comment  	  */\n" + 
    +		"	String test2= \"this\"+\n" + 
    +		"					\"is\"+\n" + 
    +		"			\"a specific\"+\n" + 
    +		"		\"line wrapping \";\n" + 
    +		"}\n" + 
    +		"}\n";
    +	formatSource(source,
    +		"public class X02 {\n" + 
    +		"	void foo() {\n" + 
    +		"/* disable-formatter */\n" + 
    +		"				/*       unformatted		comment  	  */\n" + 
    +		"	String test1= \"this\"+\n" + 
    +		"					\"is\"+\n" + 
    +		"			\"a specific\"+\n" + 
    +		"		\"line wrapping \";\n" + 
    +		"\n" + 
    +		"/* enable-formatter */\n" + 
    +		"		/* formatted comment */\n" + 
    +		"		String test2 = \"this\" + \"is\" + \"a specific\" + \"line wrapping \";\n" + 
    +		"	}\n" + 
    +		"}\n"
    +	);
    +}
    +public void testBug027079c() throws JavaModelException {
    +	this.formatterPrefs.disabling_tags = new char[][] { "disable-formatter".toCharArray() };
    +	this.formatterPrefs.enabling_tags = new char[][] { "enable-formatter".toCharArray() };
    +	String source =
    +		"public class X03 {\n" + 
    +		"void foo() {\n" + 
    +		"/* disable-formatter */\n" + 
    +		"	bar(\n" + 
    +		"				/**       unformatted		comment  	  */\n" + 
    +		"				\"this\"  ,\n" + 
    +		"					\"is\",\n" + 
    +		"			\"a specific\",\n" + 
    +		"		\"line wrapping \"\n" + 
    +		"	);\n" + 
    +		"\n" + 
    +		"/* enable-formatter */\n" + 
    +		"	bar(\n" + 
    +		"				/**       formatted		comment  	  */\n" + 
    +		"				\"this\"  ,\n" + 
    +		"					\"is\",\n" + 
    +		"			\"a specific\",\n" + 
    +		"		\"line wrapping \"\n" + 
    +		"	);\n" + 
    +		"}\n" + 
    +		"void bar(String... str) {}\n" + 
    +		"}\n";
    +	formatSource(source,
    +		"public class X03 {\n" + 
    +		"	void foo() {\n" + 
    +		"/* disable-formatter */\n" + 
    +		"	bar(\n" + 
    +		"				/**       unformatted		comment  	  */\n" + 
    +		"				\"this\"  ,\n" + 
    +		"					\"is\",\n" + 
    +		"			\"a specific\",\n" + 
    +		"		\"line wrapping \"\n" + 
    +		"	);\n" + 
    +		"\n" + 
    +		"/* enable-formatter */\n" + 
    +		"		bar(\n" + 
    +		"		/** formatted comment */\n" + 
    +		"		\"this\", \"is\", \"a specific\", \"line wrapping \");\n" + 
    +		"	}\n" + 
    +		"\n" + 
    +		"	void bar(String... str) {\n" + 
    +		"	}\n" + 
    +		"}\n"
    +	);
    +}
    +public void testBug027079d() throws JavaModelException {
    +	this.formatterPrefs.disabling_tags = new char[][] { "disable-formatter".toCharArray() };
    +	this.formatterPrefs.enabling_tags = new char[][] { "enable-formatter".toCharArray() };
    +	String source =
    +		"public class X03b {\n" + 
    +		"void foo() {\n" + 
    +		"	bar(\n" + 
    +		"// disable-formatter\n" + 
    +		"				/**       unformatted		comment  	  */\n" + 
    +		"				\"this\"  ,\n" + 
    +		"					\"is\",\n" + 
    +		"			\"a specific\",\n" + 
    +		"		\"line wrapping \"\n" + 
    +		"// enable-formatter\n" + 
    +		"	);\n" + 
    +		"	bar(\n" + 
    +		"				/**       formatted		comment  	  */\n" + 
    +		"				\"this\"  ,\n" + 
    +		"					\"is\",\n" + 
    +		"			\"a specific\",\n" + 
    +		"		\"line wrapping \"\n" + 
    +		"	);\n" + 
    +		"}\n" + 
    +		"void bar(String... str) {}\n" + 
    +		"}\n";
    +	formatSource(source,
    +		"public class X03b {\n" + 
    +		"	void foo() {\n" + 
    +		"		bar(\n" + 
    +		"// disable-formatter\n" + 
    +		"				/**       unformatted		comment  	  */\n" + 
    +		"				\"this\"  ,\n" + 
    +		"					\"is\",\n" + 
    +		"			\"a specific\",\n" + 
    +		"		\"line wrapping \"\n" + 
    +		"// enable-formatter\n" + 
    +		"		);\n" + 
    +		"		bar(\n" + 
    +		"		/** formatted comment */\n" + 
    +		"		\"this\", \"is\", \"a specific\", \"line wrapping \");\n" + 
    +		"	}\n" + 
    +		"\n" + 
    +		"	void bar(String... str) {\n" + 
    +		"	}\n" + 
    +		"}\n"
    +	);
    +}
    +public void testBug027079e() throws JavaModelException {
    +	this.formatterPrefs.disabling_tags = new char[][] { "disable-formatter".toCharArray() };
    +	this.formatterPrefs.enabling_tags = new char[][] { "enable-formatter".toCharArray() };
    +	String source =
    +		"public class X01 {\r\n" + 
    +		"\r\n" + 
    +		"/* disable-formatter */\r\n" + 
    +		"void     foo(    )      {	\r\n" + 
    +		"				//      unformatted       comment  	  \r\n" + 
    +		"}\r\n" + 
    +		"/* enable-formatter */\r\n" + 
    +		"void     bar(    )      {	\r\n" + 
    +		"				//      formatted       comment  	  \r\n" + 
    +		"}\r\n" + 
    +		"}\r\n";
    +	formatSource(source,
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"/* disable-formatter */\n" + 
    +		"void     foo(    )      {	\n" + 
    +		"				//      unformatted       comment  	  \n" + 
    +		"}\n" + 
    +		"/* enable-formatter */\n" + 
    +		"	void bar() {\n" + 
    +		"		// formatted comment\n" + 
    +		"	}\n" + 
    +		"}\n",
    +		CodeFormatter.K_COMPILATION_UNIT | CodeFormatter.F_INCLUDE_COMMENTS,
    +		0 /* indentation level */,
    +		0 /* offset */,
    +		-1 /* length (all) */,
    +		"\n",
    +		true/*repeat*/);
    +}
    +public void testBug027079f() throws JavaModelException {
    +	this.formatterPrefs.disabling_tags = new char[][] { "disable-formatter".toCharArray() };
    +	this.formatterPrefs.enabling_tags = new char[][] { "enable-formatter".toCharArray() };
    +	String source =
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"/* disable-formatter */\n" + 
    +		"void     foo(    )      {	\n" + 
    +		"				//      unformatted       comment  	  \n" + 
    +		"}\n" + 
    +		"/* enable-formatter */\n" + 
    +		"void     bar(    )      {	\n" + 
    +		"				//      formatted       comment  	  \n" + 
    +		"}\n" + 
    +		"}\n";
    +	formatSource(source,
    +		"public class X01 {\r\n" + 
    +		"\r\n" + 
    +		"/* disable-formatter */\r\n" + 
    +		"void     foo(    )      {	\r\n" + 
    +		"				//      unformatted       comment  	  \r\n" + 
    +		"}\r\n" + 
    +		"/* enable-formatter */\r\n" + 
    +		"	void bar() {\r\n" + 
    +		"		// formatted comment\r\n" + 
    +		"	}\r\n" + 
    +		"}\r\n",
    +		CodeFormatter.K_COMPILATION_UNIT | CodeFormatter.F_INCLUDE_COMMENTS,
    +		0 /* indentation level */,
    +		0 /* offset */,
    +		-1 /* length (all) */,
    +		"\r\n",
    +		true/*repeat*/);
    +}
    +public void testBug027079g() throws JavaModelException {
    +	this.formatterPrefs.disabling_tags = new char[][] { "disable-formatter".toCharArray() };
    +	this.formatterPrefs.enabling_tags = new char[][] { "enable-formatter".toCharArray() };
    +	String source =
    +		"public class X01 {\r\n" + 
    +		"\r\n" + 
    +		"/* disable-formatter */\r\n" + 
    +		"void     foo(    )      {	\r\n" + 
    +		"				//      unformatted       comment  	  \r\n" + 
    +		"}\r\n" + 
    +		"/* enable-formatter */\r\n" + 
    +		"void     bar(    )      {	\r\n" + 
    +		"				//      formatted       comment  	  \r\n" + 
    +		"}\r\n" + 
    +		"}\r\n";
    +	formatSource(source,
    +		"public class X01 {\r\n" + 
    +		"\r\n" + 
    +		"/* disable-formatter */\r\n" + 
    +		"void     foo(    )      {	\r\n" + 
    +		"				//      unformatted       comment  	  \r\n" + 
    +		"}\r\n" + 
    +		"/* enable-formatter */\r\n" + 
    +		"	void bar() {\r\n" + 
    +		"		// formatted comment\r\n" + 
    +		"	}\r\n" + 
    +		"}\r\n",
    +		CodeFormatter.K_COMPILATION_UNIT | CodeFormatter.F_INCLUDE_COMMENTS,
    +		0 /* indentation level */,
    +		0 /* offset */,
    +		-1 /* length (all) */,
    +		"\r\n",
    +		true/*repeat*/);
    +}
    +public void testBug027079h() throws JavaModelException {
    +	this.formatterPrefs.disabling_tags = new char[][] { "disable-formatter".toCharArray() };
    +	this.formatterPrefs.enabling_tags = new char[][] { "enable-formatter".toCharArray() };
    +	String source =
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"/* disable-formatter */\n" + 
    +		"void     foo(    )      {	\n" + 
    +		"				//      unformatted       comment  	  \n" + 
    +		"}\n" + 
    +		"/* enable-formatter */\n" + 
    +		"void     bar(    )      {	\n" + 
    +		"				//      formatted       comment  	  \n" + 
    +		"}\n" + 
    +		"}\n";
    +	formatSource(source,
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"/* disable-formatter */\n" + 
    +		"void     foo(    )      {	\n" + 
    +		"				//      unformatted       comment  	  \n" + 
    +		"}\n" + 
    +		"/* enable-formatter */\n" + 
    +		"	void bar() {\n" + 
    +		"		// formatted comment\n" + 
    +		"	}\n" + 
    +		"}\n",
    +		CodeFormatter.K_COMPILATION_UNIT | CodeFormatter.F_INCLUDE_COMMENTS,
    +		0 /* indentation level */,
    +		0 /* offset */,
    +		-1 /* length (all) */,
    +		"\n",
    +		true/*repeat*/);
    +}
    +public void testBug027079i() throws JavaModelException {
    +	this.formatterPrefs.disabling_tags = new char[][] { "format: off".toCharArray() };
    +	this.formatterPrefs.enabling_tags = new char[][] { "format: on".toCharArray() };
    +	String source =
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"/* format: off */\n" + 
    +		"void     foo(    )      {	\n" + 
    +		"				//      unformatted       comment\n" + 
    +		"}\n" + 
    +		"/* format: on */\n" + 
    +		"void     bar(    )      {	\n" + 
    +		"				//      formatted       comment\n" + 
    +		"}\n" + 
    +		"}\n";
    +	formatSource(source,
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"/* format: off */\n" + 
    +		"void     foo(    )      {	\n" + 
    +		"				//      unformatted       comment\n" + 
    +		"}\n" + 
    +		"/* format: on */\n" + 
    +		"	void bar() {\n" + 
    +		"		// formatted comment\n" + 
    +		"	}\n" + 
    +		"}\n"
    +	);
    +}
    +public void testBug027079j() throws JavaModelException {
    +	this.formatterPrefs.disabling_tags = new char[][] { "format: off".toCharArray() };
    +	this.formatterPrefs.enabling_tags = new char[][] { "format: on".toCharArray() };
    +	String source =
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"// format: off\n" + 
    +		"void     foo(    )      {	\n" + 
    +		"				//      unformatted       comment\n" + 
    +		"}\n" + 
    +		"// format: on\n" + 
    +		"void     bar(    )      {	\n" + 
    +		"				//      formatted       comment\n" + 
    +		"}\n" + 
    +		"}\n";
    +	formatSource(source,
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"// format: off\n" + 
    +		"void     foo(    )      {	\n" + 
    +		"				//      unformatted       comment\n" + 
    +		"}\n" + 
    +		"// format: on\n" + 
    +		"	void bar() {\n" + 
    +		"		// formatted comment\n" + 
    +		"	}\n" + 
    +		"}\n"
    +	);
    +}
    +public void testBug027079k() throws JavaModelException {
    +	this.formatterPrefs.disabling_tags = new char[][] { "format: off".toCharArray() };
    +	this.formatterPrefs.enabling_tags = new char[][] { "format: on".toCharArray() };
    +	String source =
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"/** format: off */\n" + 
    +		"void     foo(    )      {	\n" + 
    +		"				//      unformatted       comment\n" + 
    +		"}\n" + 
    +		"/** format: on */\n" + 
    +		"void     bar(    )      {	\n" + 
    +		"				//      formatted       comment\n" + 
    +		"}\n" + 
    +		"}\n";
    +	formatSource(source,
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"/** format: off */\n" + 
    +		"void     foo(    )      {	\n" + 
    +		"				//      unformatted       comment\n" + 
    +		"}\n" + 
    +		"/** format: on */\n" + 
    +		"	void bar() {\n" + 
    +		"		// formatted comment\n" + 
    +		"	}\n" + 
    +		"}\n"
    +	);
    +}
    +public void testBug027079l() throws JavaModelException {
    +	this.formatterPrefs.disabling_tags = new char[][] { "    format:  	  off    ".toCharArray() };
    +	this.formatterPrefs.enabling_tags = new char[][] { "	format:	  	on	".toCharArray() };
    +	String source =
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"/*	format:  	  off	*/\n" + 
    +		"void     foo(    )      {	\n" + 
    +		"				//      unformatted       comment\n" + 
    +		"}\n" + 
    +		"//    	format:	  	on	    \n" + 
    +		"void     bar(    )      {	\n" + 
    +		"				//      formatted       comment\n" + 
    +		"}\n" + 
    +		"}\n";
    +	formatSource(source,
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"/*	format:  	  off	*/\n" + 
    +		"void     foo(    )      {	\n" + 
    +		"				//      unformatted       comment\n" + 
    +		"}\n" + 
    +		"//    	format:	  	on	    \n" + 
    +		"	void bar() {\n" + 
    +		"		// formatted comment\n" + 
    +		"	}\n" + 
    +		"}\n"
    +	);
    +}
    +public void testBug027079m() throws JavaModelException {
    +	this.formatterPrefs.disabling_tags = new char[][] { "    format:  	  off    ".toCharArray() };
    +	this.formatterPrefs.enabling_tags = new char[][] { "	format:	  	on	".toCharArray() };
    +	String source =
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"/* format: off */\n" + 
    +		"void     foo(    )      {	\n" + 
    +		"				//      formatted       comment\n" + 
    +		"}\n" + 
    +		"/* format: on */\n" + 
    +		"void     bar(    )      {	\n" + 
    +		"				//      formatted       comment\n" + 
    +		"}\n" + 
    +		"}\n";
    +	formatSource(source,
    +		"public class X01 {\n" + 
    +		"\n" + 
    +		"	/* format: off */\n" + 
    +		"	void foo() {\n" + 
    +		"		// formatted comment\n" + 
    +		"	}\n" + 
    +		"\n" + 
    +		"	/* format: on */\n" + 
    +		"	void bar() {\n" + 
    +		"		// formatted comment\n" + 
    +		"	}\n" + 
    +		"}\n"
    +	);
    +}
    +
    +/**
      * @bug 198074: [formatter] the code formatter doesn't respect my new lines
      * @test Ensure that the formatter keep line breaks wrapping set by users in the code
      * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=198074"
    Index: src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsTests.java
    ===================================================================
    RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsTests.java,v
    retrieving revision 1.28
    diff -u -r1.28 FormatterCommentsTests.java
    --- src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsTests.java	27 Aug 2009 15:26:53 -0000	1.28
    +++ src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsTests.java	2 Mar 2010 12:50:05 -0000
    @@ -258,7 +258,7 @@
     	this.workingCopies = new ICompilationUnit[1];
     	this.workingCopies[0] = getCompilationUnit(JAVA_PROJECT.getElementName() , "", "test."+packageName, unitName); //$NON-NLS-1$ //$NON-NLS-2$
     	String outputSource = getOutputSource(this.workingCopies[0]);
    -	formatSource(this.workingCopies[0].getSource(), outputSource, kind, indentationLevel, checkNull, offset, length, lineSeparator, true);
    +	formatSource(this.workingCopies[0].getSource(), outputSource, kind, indentationLevel, offset, length, lineSeparator, true);
     }
     
     /**
    Index: src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java
    ===================================================================
    RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java,v
    retrieving revision 1.258
    diff -u -r1.258 FormatterRegressionTests.java
    --- src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java	23 Feb 2010 10:56:11 -0000	1.258
    +++ src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java	2 Mar 2010 12:50:12 -0000
    @@ -220,6 +220,11 @@
     		assertSourceEquals("Different number of length", Util.convertToIndependantLineDelimiter(expectedContents), actualContents);
     	}
     
    +	void assertLineEquals(String actualContents, String originalSource, String expectedContents) {
    +		String outputSource = expectedContents == null ? originalSource : expectedContents;
    +		assertLineEquals(actualContents, originalSource, outputSource, false /* do not check null */);
    +	}
    +
     	DefaultCodeFormatter codeFormatter() {
     		if (this.formatterOptions == null) {
     			this.formatterOptions = JAVA_PROJECT.getOptions(true);
    @@ -227,11 +232,6 @@
     		DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(this.formatterPrefs, this.formatterOptions);
     		return codeFormatter;
     	}
    -	
    -	void assertLineEquals(String actualContents, String originalSource, String expectedContents) {
    -		String outputSource = expectedContents == null ? originalSource : expectedContents;
    -		assertLineEquals(actualContents, originalSource, outputSource, false /* do not check null */);
    -	}
     
     	void formatSource(String source) {
     		// expect unchanged source after formatting
    @@ -279,11 +279,11 @@
     			}
     			assertLineEquals(result, newSource, formattedOutput);
     		} else {
    -			formatSource(source, formattedOutput, kind, indentationLevel, false, 0, -1, null, repeat);
    +			formatSource(source, formattedOutput, kind, indentationLevel, 0, -1, null, repeat);
     		}
     	}
     	
    -	void formatSource(String source, String formattedOutput, int kind, int indentationLevel, boolean checkNull, int offset, int length, String lineSeparator, boolean repeat) {
    +	void formatSource(String source, String formattedOutput, int kind, int indentationLevel, int offset, int length, String lineSeparator, boolean repeat) {
     		DefaultCodeFormatter codeFormatter = codeFormatter();
     		String result;
     		if (length == -1) {
    @@ -291,7 +291,14 @@
     		} else {
     			result = runFormatter(codeFormatter, source, kind, indentationLevel, offset, length, lineSeparator, repeat);
     		}
    -		assertLineEquals(result, source, formattedOutput);
    +		if (lineSeparator == null) {
    +			assertLineEquals(result, source, formattedOutput);
    +		} else {
    +			// Do not convert line delimiter while comparing result when a specific one is specified
    +			assertNotNull("Error(s) occured while formatting", result);
    +			String outputSource = formattedOutput == null ? source : formattedOutput;
    +			assertSourceEquals("Different number of length", outputSource, result, false/*do not convert line delimiter*/);
    +		}
     	}
     
     
    Index: src/org/eclipse/jdt/core/tests/formatter/comment/SingleLineTestCase.java
    ===================================================================
    RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/comment/SingleLineTestCase.java,v
    retrieving revision 1.10
    diff -u -r1.10 SingleLineTestCase.java
    --- src/org/eclipse/jdt/core/tests/formatter/comment/SingleLineTestCase.java	22 Feb 2010 11:01:33 -0000	1.10
    +++ src/org/eclipse/jdt/core/tests/formatter/comment/SingleLineTestCase.java	2 Mar 2010 12:50:12 -0000
    @@ -48,7 +48,7 @@
     		setUserOption(DefaultCodeFormatterConstants.FORMATTER_COMMENT_LINE_LENGTH, "5"); //$NON-NLS-1$
     		setUserOption(DefaultCodeFormatterConstants.FORMATTER_COMMENT_CLEAR_BLANK_LINES_IN_BLOCK_COMMENT, DefaultCodeFormatterConstants.FALSE);
     		setUserOption(DefaultCodeFormatterConstants.FORMATTER_COMMENT_CLEAR_BLANK_LINES_IN_JAVADOC_COMMENT, DefaultCodeFormatterConstants.FALSE);
    -		String expected = PREFIX + "test" + DELIMITER + PREFIX + "test" + DELIMITER + PREFIX + DELIMITER + PREFIX + "test";
    +		String expected = PREFIX + "test" + DELIMITER + PREFIX + "test" + DELIMITER + "//" + DELIMITER + PREFIX + "test";
     		assertEquals(expected, testFormat("//test\t\ttest" + DELIMITER + PREFIX + DELIMITER + "//\t\ttest")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
     	}
     
    @@ -192,10 +192,10 @@
     	public void testMultipleComments2() {
     		setUserOption(DefaultCodeFormatterConstants.FORMATTER_COMMENT_LINE_LENGTH, "12"); //$NON-NLS-1$
     		String expected = "// test test" + DELIMITER +
    -			"// test" + DELIMITER +
    -			"// " + DELIMITER +
    -			"// test test" + DELIMITER +
    -			"// test test";
    +				"// test" + DELIMITER +
    +				"//" + DELIMITER +
    +				"// test test" + DELIMITER +
    +				"// test test";
     		assertEquals(expected, testFormat("//test test\ttest" + DELIMITER + PREFIX + DELIMITER + PREFIX + "test test test test")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
     	}
     
    Index: src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java
    ===================================================================
    RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java,v
    retrieving revision 1.237
    diff -u -r1.237 AbstractJavaModelTests.java
    --- src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java	17 Feb 2010 15:05:54 -0000	1.237
    +++ src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java	2 Mar 2010 12:50:13 -0000
    @@ -725,11 +725,21 @@
     	 * The line separators in 'actual' are converted to '\n' before the comparison.
     	 */
     	protected void assertSourceEquals(String message, String expected, String actual) {
    +		assertSourceEquals(message, expected, actual, true/*convert line delimiter*/);
    +	}
    +	/*
    +	 * Asserts that the given actual source is equal to the expected one.
    +	 * Note that if the line separators in 'actual' are converted to '\n' before the comparison,
    +	 * 'expected' is assumed to have the same '\n' line separator.
    +	 */
    +	protected void assertSourceEquals(String message, String expected, String actual, boolean convert) {
     		if (actual == null) {
     			assertEquals(message, expected, null);
     			return;
     		}
    -		actual = org.eclipse.jdt.core.tests.util.Util.convertToIndependantLineDelimiter(actual);
    +		if (convert) {
    +			actual = org.eclipse.jdt.core.tests.util.Util.convertToIndependantLineDelimiter(actual);
    +		}
     		if (!actual.equals(expected)) {
     			System.out.println("Expected source in "+getName()+" should be:");
     			System.out.print(org.eclipse.jdt.core.tests.util.Util.displayString(actual.toString(), 2));