mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-04 06:45:43 +02:00
Bug 241355 - Added format source code save action
Change-Id: I987dda03aae1fd6c8077e2d6cd930164acfaa783 Signed-off-by: Oliver Vinn <oliver@vinn.co.uk> Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com> Reviewed-on: https://git.eclipse.org/r/21420 Reviewed-by: Elena Laskavaia <elaskavaia.cdt@gmail.com> Tested-by: Elena Laskavaia <elaskavaia.cdt@gmail.com>
This commit is contained in:
parent
67f46bce5b
commit
54607bd07f
7 changed files with 85 additions and 9 deletions
|
@ -2,7 +2,7 @@ Manifest-Version: 1.0
|
||||||
Bundle-ManifestVersion: 2
|
Bundle-ManifestVersion: 2
|
||||||
Bundle-Name: %pluginName
|
Bundle-Name: %pluginName
|
||||||
Bundle-SymbolicName: org.eclipse.cdt.ui; singleton:=true
|
Bundle-SymbolicName: org.eclipse.cdt.ui; singleton:=true
|
||||||
Bundle-Version: 5.9.0.qualifier
|
Bundle-Version: 5.10.0.qualifier
|
||||||
Bundle-Activator: org.eclipse.cdt.ui.CUIPlugin
|
Bundle-Activator: org.eclipse.cdt.ui.CUIPlugin
|
||||||
Bundle-Vendor: %providerName
|
Bundle-Vendor: %providerName
|
||||||
Bundle-Localization: plugin
|
Bundle-Localization: plugin
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<version>5.9.0-SNAPSHOT</version>
|
<version>5.10.0-SNAPSHOT</version>
|
||||||
<artifactId>org.eclipse.cdt.ui</artifactId>
|
<artifactId>org.eclipse.cdt.ui</artifactId>
|
||||||
<packaging>eclipse-plugin</packaging>
|
<packaging>eclipse-plugin</packaging>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -14,8 +14,10 @@ package org.eclipse.cdt.internal.ui.editor;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.eclipse.core.filebuffers.ITextFileBuffer;
|
import org.eclipse.core.filebuffers.ITextFileBuffer;
|
||||||
import org.eclipse.core.resources.IFile;
|
import org.eclipse.core.resources.IFile;
|
||||||
|
@ -34,14 +36,22 @@ import org.eclipse.core.runtime.jobs.ISchedulingRule;
|
||||||
import org.eclipse.jface.preference.IPreferenceStore;
|
import org.eclipse.jface.preference.IPreferenceStore;
|
||||||
import org.eclipse.jface.text.BadLocationException;
|
import org.eclipse.jface.text.BadLocationException;
|
||||||
import org.eclipse.jface.text.DefaultLineTracker;
|
import org.eclipse.jface.text.DefaultLineTracker;
|
||||||
|
import org.eclipse.jface.text.DocumentRewriteSession;
|
||||||
|
import org.eclipse.jface.text.DocumentRewriteSessionType;
|
||||||
import org.eclipse.jface.text.IDocument;
|
import org.eclipse.jface.text.IDocument;
|
||||||
|
import org.eclipse.jface.text.IDocumentExtension;
|
||||||
import org.eclipse.jface.text.IDocumentExtension3;
|
import org.eclipse.jface.text.IDocumentExtension3;
|
||||||
|
import org.eclipse.jface.text.IDocumentExtension4;
|
||||||
import org.eclipse.jface.text.ILineTracker;
|
import org.eclipse.jface.text.ILineTracker;
|
||||||
import org.eclipse.jface.text.IRegion;
|
import org.eclipse.jface.text.IRegion;
|
||||||
import org.eclipse.jface.text.ITypedRegion;
|
import org.eclipse.jface.text.ITypedRegion;
|
||||||
import org.eclipse.jface.text.Position;
|
import org.eclipse.jface.text.Position;
|
||||||
import org.eclipse.jface.text.Region;
|
import org.eclipse.jface.text.Region;
|
||||||
import org.eclipse.jface.text.TextUtilities;
|
import org.eclipse.jface.text.TextUtilities;
|
||||||
|
import org.eclipse.jface.text.formatter.FormattingContext;
|
||||||
|
import org.eclipse.jface.text.formatter.FormattingContextProperties;
|
||||||
|
import org.eclipse.jface.text.formatter.IFormattingContext;
|
||||||
|
import org.eclipse.jface.text.formatter.MultiPassContentFormatter;
|
||||||
import org.eclipse.jface.text.source.Annotation;
|
import org.eclipse.jface.text.source.Annotation;
|
||||||
import org.eclipse.jface.text.source.AnnotationModelEvent;
|
import org.eclipse.jface.text.source.AnnotationModelEvent;
|
||||||
import org.eclipse.jface.text.source.IAnnotationModel;
|
import org.eclipse.jface.text.source.IAnnotationModel;
|
||||||
|
@ -69,6 +79,7 @@ import org.eclipse.ui.texteditor.MarkerUtilities;
|
||||||
import org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel;
|
import org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel;
|
||||||
import org.eclipse.ui.texteditor.spelling.SpellingAnnotation;
|
import org.eclipse.ui.texteditor.spelling.SpellingAnnotation;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
import org.eclipse.cdt.core.model.CoreModel;
|
import org.eclipse.cdt.core.model.CoreModel;
|
||||||
import org.eclipse.cdt.core.model.ICModelMarker;
|
import org.eclipse.cdt.core.model.ICModelMarker;
|
||||||
|
@ -85,6 +96,7 @@ import org.eclipse.cdt.ui.text.ICPartitions;
|
||||||
|
|
||||||
import org.eclipse.cdt.internal.core.model.TranslationUnit;
|
import org.eclipse.cdt.internal.core.model.TranslationUnit;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.ui.text.CFormattingStrategy;
|
||||||
import org.eclipse.cdt.internal.ui.text.IProblemRequestorExtension;
|
import org.eclipse.cdt.internal.ui.text.IProblemRequestorExtension;
|
||||||
import org.eclipse.cdt.internal.ui.text.spelling.CoreSpellingProblem;
|
import org.eclipse.cdt.internal.ui.text.spelling.CoreSpellingProblem;
|
||||||
import org.eclipse.cdt.internal.ui.util.EditorUtility;
|
import org.eclipse.cdt.internal.ui.util.EditorUtility;
|
||||||
|
@ -891,22 +903,27 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
|
|
||||||
if (resource instanceof IFile && !resource.exists()) {
|
if (resource instanceof IFile && !resource.exists()) {
|
||||||
// The underlying resource has been deleted, just recreate the file, ignore the rest
|
// The underlying resource has been deleted, just recreate the file, ignore the rest
|
||||||
createFileFromDocument(monitor, (IFile) resource, document);
|
createFileFromDocument(getSubProgressMonitor(monitor, 20), (IFile) resource, document);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CoreException saveActionException= null;
|
CoreException saveActionException= null;
|
||||||
|
ICProject cproject = null;
|
||||||
try {
|
try {
|
||||||
performSaveActions(info.fTextFileBuffer, getSubProgressMonitor(monitor, 20));
|
// Project needed to obtain formatting preferences.
|
||||||
|
if (resource != null) {
|
||||||
|
cproject = CoreModel.getDefault().create(resource.getProject());
|
||||||
|
}
|
||||||
|
performSaveActions(cproject, info.fTextFileBuffer, getSubProgressMonitor(monitor, 20));
|
||||||
} catch (CoreException e) {
|
} catch (CoreException e) {
|
||||||
saveActionException = e;
|
saveActionException = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
commitFileBuffer(monitor, info, overwrite);
|
commitFileBuffer(getSubProgressMonitor(monitor, 20), info, overwrite);
|
||||||
|
|
||||||
if (saveActionException != null) {
|
if (saveActionException != null) {
|
||||||
throw saveActionException;
|
CUIPlugin.log(saveActionException);
|
||||||
}
|
}
|
||||||
} catch (CoreException x) {
|
} catch (CoreException x) {
|
||||||
// Inform about the failure
|
// Inform about the failure
|
||||||
|
@ -946,17 +963,56 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
private void formatCode(ICProject project, IDocument document) {
|
||||||
|
DocumentRewriteSession fRewriteSession = null;
|
||||||
|
|
||||||
|
if (shouldStyleFormatCode() && project != null) {
|
||||||
|
final IFormattingContext context = new FormattingContext();
|
||||||
|
try {
|
||||||
|
context.setProperty(FormattingContextProperties.CONTEXT_PREFERENCES, project.getOptions(true));
|
||||||
|
context.setProperty(FormattingContextProperties.CONTEXT_DOCUMENT, Boolean.valueOf(true));
|
||||||
|
|
||||||
|
final MultiPassContentFormatter formatter= new MultiPassContentFormatter(ICPartitions.C_PARTITIONING, IDocument.DEFAULT_CONTENT_TYPE);
|
||||||
|
formatter.setMasterStrategy(new CFormattingStrategy());
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Begin a single editing event
|
||||||
|
if (document instanceof IDocumentExtension4) {
|
||||||
|
IDocumentExtension4 extension= (IDocumentExtension4) document;
|
||||||
|
fRewriteSession= extension.startRewriteSession(DocumentRewriteSessionType.SEQUENTIAL);
|
||||||
|
} else if (document instanceof IDocumentExtension) {
|
||||||
|
IDocumentExtension extension= (IDocumentExtension) document;
|
||||||
|
extension.startSequentialRewrite(false);
|
||||||
|
}
|
||||||
|
formatter.format(document, context);
|
||||||
|
} finally {
|
||||||
|
if (fRewriteSession != null) {
|
||||||
|
IDocumentExtension4 extension= (IDocumentExtension4) document;
|
||||||
|
extension.stopRewriteSession(fRewriteSession);
|
||||||
|
} else {
|
||||||
|
IDocumentExtension extension= (IDocumentExtension)document;
|
||||||
|
extension.stopSequentialRewrite();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
context.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes trailing whitespaces from changed lines and adds newline at the end of the file,
|
* Removes trailing whitespaces from changed lines and adds newline at the end of the file,
|
||||||
* if the last line of the file was changed.
|
* if the last line of the file was changed.
|
||||||
* @throws BadLocationException
|
* @throws BadLocationException
|
||||||
*/
|
*/
|
||||||
private void performSaveActions(ITextFileBuffer buffer, IProgressMonitor monitor) throws CoreException {
|
private void performSaveActions(ICProject project, ITextFileBuffer buffer, IProgressMonitor monitor) throws CoreException {
|
||||||
if (shouldRemoveTrailingWhitespace() || shouldAddNewlineAtEof()) {
|
if (shouldRemoveTrailingWhitespace() || shouldAddNewlineAtEof() || shouldStyleFormatCode()) {
|
||||||
IRegion[] changedRegions= needsChangedRegions() ?
|
IRegion[] changedRegions= needsChangedRegions() ?
|
||||||
EditorUtility.calculateChangedLineRegions(buffer, getSubProgressMonitor(monitor, 20)) :
|
EditorUtility.calculateChangedLineRegions(buffer, getSubProgressMonitor(monitor, 20)) :
|
||||||
null;
|
null;
|
||||||
IDocument document = buffer.getDocument();
|
IDocument document = buffer.getDocument();
|
||||||
|
formatCode(project, document);
|
||||||
TextEdit edit = createSaveActionEdit(document, changedRegions);
|
TextEdit edit = createSaveActionEdit(document, changedRegions);
|
||||||
if (edit != null) {
|
if (edit != null) {
|
||||||
try {
|
try {
|
||||||
|
@ -979,6 +1035,11 @@ public class CDocumentProvider extends TextFileDocumentProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean shouldStyleFormatCode() {
|
||||||
|
return PreferenceConstants.getPreferenceStore().getBoolean(
|
||||||
|
PreferenceConstants.FORMAT_SOURCE_CODE);
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean shouldAddNewlineAtEof() {
|
private static boolean shouldAddNewlineAtEof() {
|
||||||
return PreferenceConstants.getPreferenceStore().getBoolean(
|
return PreferenceConstants.getPreferenceStore().getBoolean(
|
||||||
PreferenceConstants.ENSURE_NEWLINE_AT_EOF);
|
PreferenceConstants.ENSURE_NEWLINE_AT_EOF);
|
||||||
|
|
|
@ -185,6 +185,7 @@ public final class PreferencesMessages extends NLS {
|
||||||
public static String SaveActionsPreferencePage_inEditedLines;
|
public static String SaveActionsPreferencePage_inEditedLines;
|
||||||
public static String SaveActionsPreferencePage_inAllLines;
|
public static String SaveActionsPreferencePage_inAllLines;
|
||||||
public static String SaveActionsPreferencePage_ensureNewline;
|
public static String SaveActionsPreferencePage_ensureNewline;
|
||||||
|
public static String SaveActionsPreferencePage_formatSourceCode;
|
||||||
|
|
||||||
public static String SmartTypingConfigurationBlock_autoclose_title;
|
public static String SmartTypingConfigurationBlock_autoclose_title;
|
||||||
public static String SmartTypingConfigurationBlock_autoindent_newlines;
|
public static String SmartTypingConfigurationBlock_autoindent_newlines;
|
||||||
|
|
|
@ -116,6 +116,7 @@ SaveActionsPreferencePage_removeTrailingWhitespace=Remove trailing &whitespace
|
||||||
SaveActionsPreferencePage_inEditedLines=In &edited lines
|
SaveActionsPreferencePage_inEditedLines=In &edited lines
|
||||||
SaveActionsPreferencePage_inAllLines=In a&ll lines
|
SaveActionsPreferencePage_inAllLines=In a&ll lines
|
||||||
SaveActionsPreferencePage_ensureNewline=Ensure &newline at the end of file
|
SaveActionsPreferencePage_ensureNewline=Ensure &newline at the end of file
|
||||||
|
SaveActionsPreferencePage_formatSourceCode=&Format source code
|
||||||
|
|
||||||
TemplatePreferencePage_Viewer_preview=Preview:
|
TemplatePreferencePage_Viewer_preview=Preview:
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,8 @@ public class SaveActionsPreferencePage extends AbstractPreferencePage {
|
||||||
PreferenceConstants.REMOVE_TRAILING_WHITESPACE_LIMIT_TO_EDITED_LINES));
|
PreferenceConstants.REMOVE_TRAILING_WHITESPACE_LIMIT_TO_EDITED_LINES));
|
||||||
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN,
|
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN,
|
||||||
PreferenceConstants.ENSURE_NEWLINE_AT_EOF));
|
PreferenceConstants.ENSURE_NEWLINE_AT_EOF));
|
||||||
|
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN,
|
||||||
|
PreferenceConstants.FORMAT_SOURCE_CODE));
|
||||||
|
|
||||||
OverlayPreferenceStore.OverlayKey[] keys = new OverlayPreferenceStore.OverlayKey[overlayKeys.size()];
|
OverlayPreferenceStore.OverlayKey[] keys = new OverlayPreferenceStore.OverlayKey[overlayKeys.size()];
|
||||||
overlayKeys.toArray(keys);
|
overlayKeys.toArray(keys);
|
||||||
|
@ -94,6 +96,9 @@ public class SaveActionsPreferencePage extends AbstractPreferencePage {
|
||||||
label = PreferencesMessages.SaveActionsPreferencePage_ensureNewline;
|
label = PreferencesMessages.SaveActionsPreferencePage_ensureNewline;
|
||||||
addCheckBox(composite, label, PreferenceConstants.ENSURE_NEWLINE_AT_EOF, 0);
|
addCheckBox(composite, label, PreferenceConstants.ENSURE_NEWLINE_AT_EOF, 0);
|
||||||
|
|
||||||
|
label = PreferencesMessages.SaveActionsPreferencePage_formatSourceCode;
|
||||||
|
addCheckBox(composite, label, PreferenceConstants.FORMAT_SOURCE_CODE, 0);
|
||||||
|
|
||||||
return composite;
|
return composite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -989,6 +989,13 @@ public class PreferenceConstants {
|
||||||
*/
|
*/
|
||||||
public final static String REMOVE_TRAILING_WHITESPACE_LIMIT_TO_EDITED_LINES = "removeTrailingWhitespaceEditedLines"; //$NON-NLS-1$
|
public final static String REMOVE_TRAILING_WHITESPACE_LIMIT_TO_EDITED_LINES = "removeTrailingWhitespaceEditedLines"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Style format code on save
|
||||||
|
*
|
||||||
|
* @since 5.10
|
||||||
|
*/
|
||||||
|
public final static String FORMAT_SOURCE_CODE = "formatSourceCode"; //$NON-NLS-1$
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A named preference that defines whether the hint to make hover sticky should be shown.
|
* A named preference that defines whether the hint to make hover sticky should be shown.
|
||||||
*
|
*
|
||||||
|
@ -2190,6 +2197,7 @@ public class PreferenceConstants {
|
||||||
store.setDefault(REMOVE_TRAILING_WHITESPACE, true);
|
store.setDefault(REMOVE_TRAILING_WHITESPACE, true);
|
||||||
store.setDefault(REMOVE_TRAILING_WHITESPACE_LIMIT_TO_EDITED_LINES, true);
|
store.setDefault(REMOVE_TRAILING_WHITESPACE_LIMIT_TO_EDITED_LINES, true);
|
||||||
store.setDefault(ENSURE_NEWLINE_AT_EOF, true);
|
store.setDefault(ENSURE_NEWLINE_AT_EOF, true);
|
||||||
|
store.setDefault(PreferenceConstants.FORMAT_SOURCE_CODE, false);
|
||||||
|
|
||||||
// Formatter profile
|
// Formatter profile
|
||||||
store.setDefault(FORMATTER_PROFILE, FormatterProfileManager.DEFAULT_PROFILE);
|
store.setDefault(FORMATTER_PROFILE, FormatterProfileManager.DEFAULT_PROFILE);
|
||||||
|
|
Loading…
Add table
Reference in a new issue