From 65673a50e15988ab8840f73eca11e2423db301d4 Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Mon, 7 Nov 2011 10:57:47 -0800 Subject: [PATCH] Added a method for formatting multiple regions in a single call. --- .../cdt/core/formatter/CodeFormatter.java | 40 +++++++-- .../internal/formatter/CCodeFormatter.java | 82 ++++++++++++++++++- 2 files changed, 113 insertions(+), 9 deletions(-) diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/CodeFormatter.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/CodeFormatter.java index 0ad5f9b5e16..3186172f93a 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/CodeFormatter.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/CodeFormatter.java @@ -13,6 +13,7 @@ package org.eclipse.cdt.core.formatter; import java.util.Map; +import org.eclipse.jface.text.IRegion; import org.eclipse.text.edits.TextEdit; /** @@ -64,15 +65,15 @@ public abstract class CodeFormatter { public static final int K_MULTI_LINE_COMMENT = 0x20; /** - * Format source, - * and returns a text edit that correspond to the difference between the given string and - * the formatted string. It returns null if the given string cannot be formatted. + * Formats source, and returns a text edit that correspond to the difference + * between the given string and the formatted string. It returns null if the given string cannot + * be formatted. * * If the offset position is matching a whitespace, the result can include whitespaces. * It would be up to the caller to get rid of preceding whitespaces. * * @param kind Use to specify the kind of the code snippet to format. It can be any of these: - * K_EXPRESSION, K_STATEMENTS, K_CLASS_BODY_DECLARATIONS, K_TRANSLATION_UNIT, K_UNKNOWN + * K_EXPRESSION, K_STATEMENTS, K_CLASS_BODY_DECLARATIONS, K_TRANSLATION_UNIT, K_UNKNOWN * @param source the document to format * @param offset the given offset to start recording the edits (inclusive). * @param length the given length to stop recording the edits (exclusive). @@ -87,7 +88,36 @@ public abstract class CodeFormatter { */ public abstract TextEdit format(int kind, String source, int offset, int length, int indentationLevel, String lineSeparator); - + + /** + * Formats one or more regions of source, and returns an array of edits, one edit + * per region. If some of the regions cannot be formatted, the corresponding elements of + * the returned array will be null. + * + * If the offset of a region is matching a whitespace, the result can include whitespaces. + * It would be up to the caller to get rid of preceding whitespaces. + * + * Subclasses may override this method to provide a more efficient implementation. + * + * @param kind Use to specify the kind of the code snippet to format. It can be any of these: + * K_EXPRESSION, K_STATEMENTS, K_CLASS_BODY_DECLARATIONS, K_TRANSLATION_UNIT, K_UNKNOWN. + * @param source the document to format. + * @param regions regions of the source to be formatted. + * @param lineSeparator the line separator to use in formatted source, + * if set to null, then the platform default one will be used. + * @return the text edits, one per region. + * @throws IllegalArgumentException if any of the regions is invalid. + * @since 5.4 + */ + public TextEdit[] format(int kind, String source, IRegion[] regions, String lineSeparator) { + TextEdit[] edits = new TextEdit[regions.length]; + for (int i = 0; i < regions.length; i++) { + IRegion region = regions[i]; + edits[i] = format(kind, source, region.getOffset(), region.getLength(), 0, lineSeparator); + } + return edits; + } + /** * @param options - general formatter options */ diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CCodeFormatter.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CCodeFormatter.java index 12a08dbb697..bdc678c626a 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CCodeFormatter.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CCodeFormatter.java @@ -7,7 +7,7 @@ * * Contributors: * QNX Software Systems - Initial API and implementation - * Sergey Prigogin, Google + * Sergey Prigogin (Google) * Anton Leherbauer (Wind River Systems) * IBM Corporation *******************************************************************************/ @@ -34,6 +34,7 @@ import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.text.edits.TextEdit; +import org.eclipse.jface.text.IRegion; public class CCodeFormatter extends CodeFormatter { private DefaultCodeFormatterOptions preferences; @@ -117,9 +118,6 @@ public class CCodeFormatter extends CodeFormatter { } } - /* - * @see org.eclipse.cdt.core.formatter.CodeFormatter#format(int, java.lang.String, int, int, int, java.lang.String) - */ @Override public TextEdit format(int kind, String source, int offset, int length, int indentationLevel, String lineSeparator) { TextEdit edit= null; @@ -188,4 +186,80 @@ public class CCodeFormatter extends CodeFormatter { } return edit; } + + @Override + public TextEdit[] format(int kind, String source, IRegion[] regions, String lineSeparator) { + TextEdit[] edits= new TextEdit[regions.length]; + ITranslationUnit tu= (ITranslationUnit) options.get(DefaultCodeFormatterConstants.FORMATTER_TRANSLATION_UNIT); + if (tu == null) { + IFile file= (IFile) options.get(DefaultCodeFormatterConstants.FORMATTER_CURRENT_FILE); + if (file != null) { + tu= (ITranslationUnit) CoreModel.getDefault().create(file); + } + } + if (lineSeparator != null) { + preferences.line_separator = lineSeparator; + } else { + preferences.line_separator = System.getProperty("line.separator"); //$NON-NLS-1$ + } + + if (tu != null) { + IIndex index; + try { + index = CCorePlugin.getIndexManager().getIndex(tu.getCProject()); + index.acquireReadLock(); + } catch (CoreException e) { + throw new AbortFormatting(e); + } catch (InterruptedException e) { + return null; + } + IASTTranslationUnit ast; + try { + try { + ast= tu.getAST(index, ITranslationUnit.AST_SKIP_ALL_HEADERS); + } catch (CoreException exc) { + throw new AbortFormatting(exc); + } + for (int i = 0; i < regions.length; i++) { + IRegion region = regions[i]; + CodeFormatterVisitor codeFormatter = + new CodeFormatterVisitor(preferences, region.getOffset(), region.getLength()); + edits[i] = codeFormatter.format(source, ast); + IStatus status= codeFormatter.getStatus(); + if (!status.isOK()) { + CCorePlugin.log(status); + } + } + } finally { + index.releaseReadLock(); + } + } else { + IncludeFileContentProvider contentProvider = IncludeFileContentProvider.getSavedFilesProvider(); + IScannerInfo scanInfo = new ScannerInfo(); + FileContent content = FileContent.create("", source.toCharArray()); //$NON-NLS-1$ + + ILanguage language= (ILanguage) options.get(DefaultCodeFormatterConstants.FORMATTER_LANGUAGE); + if (language == null) { + language= GPPLanguage.getDefault(); + } + IASTTranslationUnit ast; + try { + ast= language.getASTTranslationUnit(content, scanInfo, contentProvider, null, 0, + ParserUtil.getParserLogService()); + for (int i = 0; i < regions.length; i++) { + IRegion region = regions[i]; + CodeFormatterVisitor codeFormatter = + new CodeFormatterVisitor(preferences, region.getOffset(), region.getLength()); + edits[i]= codeFormatter.format(source, ast); + IStatus status= codeFormatter.getStatus(); + if (!status.isOK()) { + CCorePlugin.log(status); + } + } + } catch (CoreException e) { + throw new AbortFormatting(e); + } + } + return edits; + } }