/*
* Copyright (c) 2012, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.dart.tools.ui.internal.text.editor.saveactions;
import com.google.dart.tools.ui.DartToolsPlugin;
import com.google.dart.tools.ui.internal.cleanup.MultiFixMessages;
import com.google.dart.tools.ui.text.DartPartitions;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.BadPartitioningException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension3;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.ltk.core.refactoring.CategorizedTextEditGroup;
import org.eclipse.ltk.core.refactoring.GroupCategory;
import org.eclipse.ltk.core.refactoring.GroupCategorySet;
import org.eclipse.text.edits.DeleteEdit;
import org.eclipse.text.edits.MultiTextEdit;
/**
* A factory for creating text edits to perform simple formating tasks (such as removing trailing
* whitespace).
* <p>
* NOTE: this is a dumbed-down implementation of the kind of things that {@link ICleanUpFix}s do in
* the JDT. If we elect to enable full-blown cleanups, this can get removed or folded in.
*/
public class CodeFormatEditFactory {
/**
* Create an edit that removes trailing whitespace (not in a multi-line string) from the given
* document.
*
* @param document the document to clean up
* @return an edit that removes all trailing whitespace
* @throws CoreException if an error occurs in creating the edit
*/
public static MultiTextEdit removeTrailingWhitespace(IDocument document) throws CoreException {
MultiTextEdit textEdit = new MultiTextEdit();
try {
String label = MultiFixMessages.CodeFormatFix_RemoveTrailingWhitespace_changeDescription;
CategorizedTextEditGroup group = new CategorizedTextEditGroup(label, new GroupCategorySet(
new GroupCategory(label, label, label)));
int lineCount = document.getNumberOfLines();
for (int i = 0; i < lineCount; i++) {
IRegion region = document.getLineInformation(i);
if (region.getLength() == 0) {
continue;
}
int lineStart = region.getOffset();
int lineExclusiveEnd = lineStart + region.getLength();
if (inMultilineString(document, lineExclusiveEnd)) {
continue;
}
int j = getIndexOfRightMostNoneWhitespaceCharacter(
lineStart,
lineExclusiveEnd - 1,
document);
j++;
if (j < lineExclusiveEnd) {
DeleteEdit edit = new DeleteEdit(j, lineExclusiveEnd - j);
textEdit.addChild(edit);
group.addTextEdit(edit);
}
}
} catch (BadLocationException e) {
throw new CoreException(new Status(IStatus.ERROR, DartToolsPlugin.getPluginId(), 0, "", e)); //$NON-NLS-1$
} catch (BadPartitioningException e) {
throw new CoreException(new Status(IStatus.ERROR, DartToolsPlugin.getPluginId(), 0, "", e)); //$NON-NLS-1$
}
return textEdit;
}
/**
* Returns the index in document of a none whitespace character between start (inclusive) and end
* (inclusive) such that if more then one such character the index returned is the largest
* possible (closest to end). Returns start - 1 if no such character.
*
* @param start the start
* @param end the end
* @param document the document
* @return the position or start - 1
* @exception BadLocationException if the offset is invalid in this document
*/
private static int getIndexOfRightMostNoneWhitespaceCharacter(int start, int end,
IDocument document) throws BadLocationException {
int position = end;
while (position >= start && Character.isWhitespace(document.getChar(position))) {
position--;
}
return position;
}
private static boolean inMultilineString(IDocument document, int offset)
throws BadLocationException, BadPartitioningException {
try {
ITypedRegion partitionInfo = ((IDocumentExtension3) document).getPartition(
DartPartitions.DART_PARTITIONING,
offset,
true);
return (partitionInfo.getType().equals(DartPartitions.DART_MULTI_LINE_STRING));
} catch (BadPartitioningException ex) {
return false;
}
}
}