blob: 7b6407b9c690051674d9f05d75f0ca94bd724e9e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2008 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
*******************************************************************************/
package org.eclipse.wst.jsdt.core.tests.formatter.comment;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.wst.jsdt.core.JavaScriptCore;
import org.eclipse.wst.jsdt.core.ToolFactory;
import org.eclipse.wst.jsdt.core.formatter.CodeFormatter;
import org.eclipse.wst.jsdt.core.formatter.DefaultCodeFormatterConstants;
/**
* Utilities for the comment formatter.
*
* @since 3.0
*/
public class CommentFormatterUtil {
/**
* Formats the source string as a comment region of the specified kind.
* <p>
* Both offset and length must denote a valid comment partition, that is
* to say a substring that starts and ends with the corresponding
* comment delimiter tokens.
*
* @param kind the kind of the comment
* @param source the source string to format
* @param offset the offset relative to the source string where to
* format
* @param length the length of the region in the source string to format
* @param preferences preferences for the comment formatter
* @return the formatted source string
*/
public static String format(int kind, String source, int offset, int length, Map preferences) {
Assert.isNotNull(source);
IDocument document= new Document(source);
try {
int indentOffset= document.getLineOffset(document.getLineOfOffset(offset));
int indentationLevel= inferIndentationLevel(document.get(indentOffset, offset - indentOffset), getTabSize(preferences));
return format(kind, source, offset, length, indentationLevel, preferences);
} catch (BadLocationException x) {
throw new RuntimeException(x);
}
}
/**
* Formats the source string as a comment region of the specified kind.
* <p>
* Both offset and length must denote a valid comment partition, that is
* to say a substring that starts and ends with the corresponding
* comment delimiter tokens.
*
* @param kind the kind of the comment
* @param source the source string to format
* @param offset the offset relative to the source string where to
* format
* @param length the length of the region in the source string to format
* @param preferences preferences for the comment formatter
* @return the formatted source string
*/
public static String format(int kind, String source, int offset, int length, int indentationLevel, Map preferences) {
Assert.isTrue(kind == CodeFormatter.K_JAVA_DOC || kind == CodeFormatter.K_MULTI_LINE_COMMENT || kind == CodeFormatter.K_SINGLE_LINE_COMMENT);
Assert.isNotNull(source);
Assert.isNotNull(preferences);
Assert.isTrue(offset >= 0);
Assert.isTrue(length <= source.length());
IDocument document= new Document(source);
TextEdit edit;
edit= ToolFactory.createCodeFormatter(preferences).format(kind, source, offset, length, indentationLevel, TextUtilities.getDefaultLineDelimiter(document));
try {
if (edit != null)
edit.apply(document);
} catch (MalformedTreeException x) {
throw new RuntimeException(x);
} catch (BadLocationException x) {
throw new RuntimeException(x);
}
return document.get();
}
/**
* Infer the indentation level based on the given reference indentation,
* tab size and text measurement.
*
* @param reference the reference indentation
* @param tabSize the tab size
* @return the inferred indentation level
* @since 3.1
*/
private static int inferIndentationLevel(String reference, int tabSize) {
StringBuffer expanded= expandTabs(reference, tabSize);
int spaceWidth, referenceWidth;
spaceWidth= 1;
referenceWidth= expanded.length();
int level= referenceWidth / (tabSize * spaceWidth);
if (referenceWidth % (tabSize * spaceWidth) > 0)
level++;
return level;
}
/**
* Expands the given string's tabs according to the given tab size.
*
* @param string the string
* @param tabSize the tab size
* @return the expanded string
* @since 3.1
*/
private static StringBuffer expandTabs(String string, int tabSize) {
StringBuffer expanded= new StringBuffer();
for (int i= 0, n= string.length(), chars= 0; i < n; i++) {
char ch= string.charAt(i);
if (ch == '\t') {
for (; chars < tabSize; chars++)
expanded.append(' ');
chars= 0;
} else {
expanded.append(ch);
chars++;
if (chars >= tabSize)
chars= 0;
}
}
return expanded;
}
/**
* Returns the value of {@link DefaultCodeFormatterConstants#FORMATTER_TAB_SIZE}
* from the given preferences.
*
* @param preferences the preferences
* @return the value of {@link DefaultCodeFormatterConstants#FORMATTER_TAB_SIZE}
* from the given preferences
* @since 3.1
*/
private static int getTabSize(Map preferences) {
if (preferences.containsKey(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE))
try {
return Integer.parseInt((String) preferences.get(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE));
} catch (NumberFormatException e) {
// use default
}
return 4;
}
/**
* Creates a formatting options with all default options and the given custom user options.
*
* @param user the custom user options
* @return the formatting options
* @since 3.1
*/
public static Map createOptions(Map user) {
final Map map= JavaScriptCore.getOptions();
if (user != null) {
for (final Iterator iterator= user.keySet().iterator(); iterator.hasNext();) {
Object key= iterator.next();
Object value = user.get(key);
map.put(key, value);
}
}
return map;
}
}