Skip to content

Format on Save #145

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,53 @@
*
* Contributors:
* Angelo Zerr <[email protected]> - initial API and implementation
* Lorenzo Dalla Vecchia <[email protected]> - added save actions
*/
package ts.eclipse.ide.jsdt.internal.ui.editor;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.IDocument;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.CompositeChange;
import org.eclipse.ltk.core.refactoring.IUndoManager;
import org.eclipse.ltk.core.refactoring.PerformChangeOperation;
import org.eclipse.ltk.core.refactoring.RefactoringCore;
import org.eclipse.ltk.core.refactoring.TextFileChange;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.editors.text.ForwardingDocumentProvider;
import org.eclipse.ui.editors.text.TextFileDocumentProvider;
import org.eclipse.ui.preferences.ScopedPreferenceStore;
import org.eclipse.ui.texteditor.ChainedPreferenceStore;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.wst.jsdt.internal.ui.javaeditor.JavaDocumentSetupParticipant;
import org.eclipse.wst.jsdt.ui.text.IJavaScriptPartitions;

import ts.client.CodeEdit;
import ts.eclipse.ide.core.TypeScriptCorePlugin;
import ts.eclipse.ide.core.resources.IIDETypeScriptFile;
import ts.eclipse.ide.core.resources.IIDETypeScriptProject;
import ts.eclipse.ide.core.utils.DocumentUtils;
import ts.eclipse.ide.core.utils.TypeScriptResourceUtil;
import ts.eclipse.ide.jsdt.internal.ui.JSDTTypeScriptUIPlugin;
import ts.eclipse.ide.ui.TypeScriptUIPlugin;
import ts.eclipse.ide.ui.preferences.TypeScriptUIPreferenceConstants;

public class TypeScriptDocumentProvider extends TextFileDocumentProvider {

public TypeScriptDocumentProvider() {
Expand All @@ -26,11 +62,115 @@ public TypeScriptDocumentProvider() {
new JavaDocumentSetupParticipant(), provider);
setParentDocumentProvider(provider);
}

@Override
protected DocumentProviderOperation createSaveOperation(Object element, IDocument document, boolean overwrite)
throws CoreException {
// TODO Auto-generated method stub
return super.createSaveOperation(element, document, overwrite);
final DocumentProviderOperation delegate = super.createSaveOperation(element, document, overwrite);
return new DocumentProviderOperation() {
@Override
protected void execute(IProgressMonitor monitor) throws CoreException {
SubMonitor progress = SubMonitor.convert(monitor, 10);

// Retrieve the file that is being saved
IFile file = getFile(element);
if (file == null) {
return;
}
IPreferenceStore preferenceStore = createProjectSpecificPreferenceStore(file.getProject());
boolean runSaveActions = preferenceStore
.getBoolean(TypeScriptUIPreferenceConstants.EDITOR_SAVE_ACTIONS);

try {
delegate.run(progress.newChild(8));
if (runSaveActions) {
try {
performSaveActions(file, document, progress.newChild(2), preferenceStore);
} catch (Exception e) {
JSDTTypeScriptUIPlugin.log(e);
}
} else {
progress.setWorkRemaining(0);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (InvocationTargetException e) {
throw new CoreException(
new Status(IStatus.ERROR, TypeScriptCorePlugin.PLUGIN_ID, "Error while saving " + file, e));
}
}
};
}

private void performSaveActions(IFile file, IDocument document, IProgressMonitor monitor,
IPreferenceStore preferenceStore) {
boolean runFormat = preferenceStore.getBoolean(TypeScriptUIPreferenceConstants.EDITOR_SAVE_ACTIONS_FORMAT);
SubMonitor progress = SubMonitor.convert(monitor, (runFormat ? 10 : 0));
if (!runFormat) {
return;
}

IUndoManager manager = RefactoringCore.getUndoManager();

CompositeChange saveActionsChange = new CompositeChange("Save Actions");
List<Change> undoChanges = new ArrayList<>();
boolean success = false;
try {
manager.aboutToPerformChange(saveActionsChange);

// Format the file contents
if (runFormat) {
TextFileChange change = new TextFileChange("Format", file);
try {
IIDETypeScriptProject tsProject = TypeScriptResourceUtil.getTypeScriptProject(file.getProject());
final IIDETypeScriptFile tsFile = tsProject.openFile(file, document);
List<CodeEdit> codeEdits = tsFile.format(0, document.getLength()).get();
change.setEdit(DocumentUtils.toTextEdit(codeEdits, document));
change.initializeValidationData(new NullProgressMonitor());
PerformChangeOperation performChangeOperation = new PerformChangeOperation(change);
ResourcesPlugin.getWorkspace().run(performChangeOperation, progress.newChild(10));
Change undoChange = performChangeOperation.getUndoChange();
if (undoChange != null) {
undoChanges.add(undoChange);
}
} catch (Exception e) {
JSDTTypeScriptUIPlugin.log(e);
}
}

success = true;
} finally {
manager.changePerformed(saveActionsChange, success);
}

// Add an undo change if possible
if (!undoChanges.isEmpty()) {
manager.addUndo(saveActionsChange.getName(), new CompositeChange(saveActionsChange.getName(),
undoChanges.toArray(new Change[undoChanges.size()])));
}
}

private static IPreferenceStore createProjectSpecificPreferenceStore(IProject project) {
List<IPreferenceStore> stores = new ArrayList<IPreferenceStore>();
if (project != null) {
stores.add(new EclipsePreferencesAdapter(new ProjectScope(project), TypeScriptUIPlugin.PLUGIN_ID));
stores.add(new EclipsePreferencesAdapter(new ProjectScope(project), TypeScriptCorePlugin.PLUGIN_ID));
}
stores.add(new ScopedPreferenceStore(InstanceScope.INSTANCE, TypeScriptUIPlugin.PLUGIN_ID));
stores.add(new ScopedPreferenceStore(InstanceScope.INSTANCE, TypeScriptCorePlugin.PLUGIN_ID));
stores.add(new ScopedPreferenceStore(DefaultScope.INSTANCE, TypeScriptUIPlugin.PLUGIN_ID));
stores.add(new ScopedPreferenceStore(DefaultScope.INSTANCE, TypeScriptCorePlugin.PLUGIN_ID));
return new ChainedPreferenceStore(stores.toArray(new IPreferenceStore[stores.size()]));
}

private IFile getFile(Object element) {
return getFile(getFileInfo(element));
}

private IFile getFile(FileInfo fileInfo) {
if (fileInfo != null && fileInfo.fElement instanceof IFileEditorInput) {
return ((IFileEditorInput) fileInfo.fElement).getFile();
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
/**
* Copyright (c) 2015-2016 Angelo ZERR.
* 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:
* Angelo Zerr <[email protected]> - initial API and implementation
* Lorenzo Dalla Vecchia <[email protected]> - made toTextEdit public
*/
package ts.eclipse.ide.core.utils;

import java.util.List;
Expand Down Expand Up @@ -67,7 +78,19 @@ public static void applyEdits(IDocument document, List<CodeEdit> codeEdits)
}
}

private static TextEdit toTextEdit(List<CodeEdit> codeEdits, IDocument document) throws TypeScriptException {
/**
* Transforms a list of documents edits into a standard {@link TextEdit}
* object that can be used for more complex operations, such as with the
* refactoring API.
*
* @param codeEdits
* list of TypeScript {@link CodeEdit}.
* @param document
* document to use as context for validating edit positions.
* @return a {@link TextEdit} object.
* @throws TypeScriptException
*/
public static TextEdit toTextEdit(List<CodeEdit> codeEdits, IDocument document) throws TypeScriptException {
MultiTextEdit textEdit = new MultiTextEdit();
for (CodeEdit codeEdit : codeEdits) {
toTextEdit(codeEdit, document, textEdit);
Expand Down
2 changes: 2 additions & 0 deletions eclipse/ts.eclipse.ide.ui/plugin.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#
# Contributors:
# Angelo Zerr <[email protected]> - Initial API and implementation
# Lorenzo Dalla Vecchia <[email protected]> - Added save actions
###############################################################################
pluginName=TypeScript - Eclipse - UI IDE
providerName=Angelo ZERR
Expand All @@ -29,6 +30,7 @@ EditorPreferencePage.name=Editor
FormatterPreferencePage.name=Formatter
ValidationPreferencePage.name=Validation
TextMatePreferencePage.name=TextMate
SaveActionsPreferencePage.name=Save Actions

# Menu/Commands
TypeScript.root.name=TypeScript
Expand Down
25 changes: 23 additions & 2 deletions eclipse/ts.eclipse.ide.ui/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#
# Contributors:
# Angelo Zerr <[email protected]> - Initial API and implementation
# Lorenzo Dalla Vecchia <[email protected]> - Added save actions
###############################################################################
-->
<plugin>
Expand Down Expand Up @@ -238,7 +239,13 @@
class="ts.eclipse.ide.internal.ui.preferences.TextMatePreferencePage"
id="ts.eclipse.ide.ui.preference.TextMatePreferencePage"
category="ts.eclipse.ide.ui.preference.EditorPreferencePage">
</page>
</page>
<page
category="ts.eclipse.ide.ui.preference.EditorPreferencePage"
class="ts.eclipse.ide.internal.ui.preferences.SaveActionsPreferencePage"
id="ts.eclipse.ide.ui.preference.SaveActionsPreferencePage"
name="%SaveActionsPreferencePage.name">
</page>
</extension>

<!-- Property Pages -->
Expand Down Expand Up @@ -330,7 +337,21 @@
<test property="ts.eclipse.ide.core.isTypeScriptProject" />
</adapt>
</enabledWhen>
</page>
</page>
<page
category="ts.eclipse.ide.ui.property.EditorPreferencePage"
class="ts.eclipse.ide.internal.ui.preferences.SaveActionsPreferencePage"
id="ts.eclipse.ide.ui.property.SaveActionsPreferencePage"
name="%SaveActionsPreferencePage.name">
<enabledWhen>
<adapt
type="org.eclipse.core.resources.IProject">
<test
property="ts.eclipse.ide.core.isTypeScriptProject">
</test>
</adapt>
</enabledWhen>
</page>
</extension>

<!-- Search -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*
* Contributors:
* Angelo Zerr <[email protected]> - initial API and implementation
* Lorenzo Dalla Vecchia <[email protected]> - Added save actions
*/
package ts.eclipse.ide.internal.ui;

Expand Down Expand Up @@ -95,6 +96,10 @@ public class TypeScriptUIMessages extends NLS {
public static String FormatterConfigurationBlock_formatOptions_placeOpenBraceOnNewLineForFunctions;
public static String FormatterConfigurationBlock_formatOptions_placeOpenBraceOnNewLineForControlBlocks;

// Save actions
public static String SaveActionsPreferencePage_performTheSelectedActionsOnSave;
public static String SaveActionsPreferencePage_formatSourceCode;

public static String ValidationConfigurationBlock_tslintjson_group_label;
public static String ValidationConfigurationBlock_tslintjson_strategy_DisableTslint;
public static String ValidationConfigurationBlock_tslintjson_strategy_UseDefaultTslintJson;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#
# Contributors:
# Angelo Zerr <[email protected]> - Initial API and implementation
# Lorenzo Dalla Vecchia <[email protected]> - Added save actions
###############################################################################

# Buttons
Expand Down Expand Up @@ -79,6 +80,10 @@ FormatterConfigurationBlock_formatOptions_insertSpaceAfterOpeningAndBeforeClosin
FormatterConfigurationBlock_formatOptions_placeOpenBraceOnNewLineForFunctions=Defines whether an open brace is put onto a new line for functions or not.
FormatterConfigurationBlock_formatOptions_placeOpenBraceOnNewLineForControlBlocks=Defines whether an open brace is put onto a new line for control blocks or not.

# Save actions
SaveActionsPreferencePage_performTheSelectedActionsOnSave=Perform the selected actions on save
SaveActionsPreferencePage_formatSourceCode=Format source code

ValidationConfigurationBlock_tslintjson_group_label=Configuration for 'tslint.json'
ValidationConfigurationBlock_tslintjson_strategy_DisableTslint=Disable tslint
ValidationConfigurationBlock_tslintjson_strategy_UseDefaultTslintJson=Use the default 'tslint.json'.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*
* Contributors:
* Angelo Zerr <[email protected]> - initial API and implementation
* Lorenzo Dalla Vecchia <[email protected]> - added reconcileControls hook
*/
package ts.eclipse.ide.internal.ui.preferences;

Expand All @@ -17,8 +18,6 @@
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;

Expand Down Expand Up @@ -69,13 +68,7 @@ public void enablePreferenceContent(boolean enable) {
}

@Override
protected Control createContents(Composite parent) {
Composite nodejsComposite = createUI(parent);
validateSettings(null, null, null);
return nodejsComposite;
}

private Composite createUI(Composite parent) {
protected Composite createUI(Composite parent) {
final ScrolledPageContent pageContent = new ScrolledPageContent(parent);
Composite composite = pageContent.getBody();
GridLayout layout = new GridLayout();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*
* Contributors:
* Angelo Zerr <[email protected]> - initial API and implementation
* Lorenzo Dalla Vecchia <[email protected]> - added reconcileControls hook
*/
package ts.eclipse.ide.internal.ui.preferences;

Expand All @@ -23,7 +24,6 @@
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;

Expand Down Expand Up @@ -55,13 +55,7 @@ public AbstractTypeScriptRepositoryConfigurationBlock(IStatusChangeListener cont
}

@Override
protected Control createContents(Composite parent) {
Composite contents = createUI(parent);
validateSettings(null, null, null);
return contents;
}

private Composite createUI(Composite parent) {
protected Composite createUI(Composite parent) {
final ScrolledPageContent pageContent = new ScrolledPageContent(parent);
Composite composite = pageContent.getBody();
GridLayout layout = new GridLayout();
Expand Down
Loading