package org.jenerate.internal.generate.method.util.impl; import org.eclipse.core.runtime.Platform; import org.eclipse.jdt.core.IBuffer; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.ISourceReference; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.ToolFactory; import org.eclipse.jdt.core.formatter.CodeFormatter; import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.Document; import org.eclipse.swt.SWT; import org.eclipse.text.edits.TextEdit; import org.jenerate.internal.generate.method.util.JavaCodeFormatter; /** * Default implementation of the {@link JavaCodeFormatter} * * @author jiayun */ public final class JavaCodeFormatterImpl implements JavaCodeFormatter { @Override public String formatCode(IType objectClass, String source) throws JavaModelException, BadLocationException { String lineDelim = getLineDelimiterUsed(objectClass); int indent = getUsedIndentation(objectClass) + 1; TextEdit textEdit = ToolFactory.createCodeFormatter(null).format(CodeFormatter.K_CLASS_BODY_DECLARATIONS, source, 0, source.length(), indent, lineDelim); if (textEdit == null) { return source; } Document document = new Document(source); textEdit.apply(document); return document.get(); } /** * Examines a string and returns the first line delimiter found. */ private static String getLineDelimiterUsed(IJavaElement elem) throws JavaModelException { ICompilationUnit cu = (ICompilationUnit) elem.getAncestor(IJavaElement.COMPILATION_UNIT); if (cu != null && cu.exists()) { IBuffer buf = cu.getBuffer(); int length = buf.getLength(); for (int i = 0; i < length; i++) { char ch = buf.getChar(i); if (ch == SWT.CR) { if (i + 1 < length) { if (buf.getChar(i + 1) == SWT.LF) { return "\r\n"; } } return "\r"; } else if (ch == SWT.LF) { return "\n"; } } } return System.getProperty("line.separator", "\n"); } /** * Evaluates the indentation used by a Java element. (in tabulators) */ private int getUsedIndentation(IJavaElement elem) throws JavaModelException { if (elem instanceof ISourceReference) { ICompilationUnit cu = (ICompilationUnit) elem.getAncestor(IJavaElement.COMPILATION_UNIT); if (cu != null) { IBuffer buf = cu.getBuffer(); int offset = ((ISourceReference) elem).getSourceRange().getOffset(); int i = offset; // find beginning of line while (i > 0 && !isLineDelimiterChar(buf.getChar(i - 1))) { i--; } return computeIndent(buf.getText(i, offset - i), getTabWidth()); } } return 0; } private int getTabWidth() { return Platform.getPreferencesService().getInt("org.eclipse.jdt.core", DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, 4, null); } /** * Indent char is a space char but not a line delimiters. * <code>== Character.isWhitespace(ch) && ch != '\n' && ch != '\r'</code> */ private boolean isIndentChar(char ch) { return Character.isWhitespace(ch) && !isLineDelimiterChar(ch); } /** * Line delimiter chars are '\n' and '\r'. */ private boolean isLineDelimiterChar(char ch) { return ch == '\n' || ch == '\r'; } /** * Returns the indent of the given string. * * @param line the text line * @param tabWidth the width of the '\t' character. */ private int computeIndent(String line, int tabWidth) { int result = 0; int blanks = 0; int size = line.length(); for (int i = 0; i < size; i++) { char c = line.charAt(i); if (c == '\t') { result++; blanks = 0; } else if (isIndentChar(c)) { blanks++; if (blanks == tabWidth) { result++; blanks = 0; } } else { return result; } } return result; } }