Skip to content

Commit

Permalink
Fix editor sync bug, when model file was edited outside of eclipse.
Browse files Browse the repository at this point in the history
This bugfix contains the fix for unsync workspace files wrt. the file
system (see the
DirtyStateEditorSupportIntegrationTest.testModifyFileInExternEditor) and
a one liner for beeing able to save the file when the changes were
ignored. (see the ignored test case
DirtyStateEditorSupportIntegrationTest.testModifyDirtyFileInExternEditor).

The issue for this fix can be found here:
#2385
  • Loading branch information
mehmet-karaman committed Aug 21, 2024
1 parent d08d131 commit be83d08
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,35 @@
*/
package org.eclipse.xtext.ui.tests.editor;

import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.emf.common.util.URI;
import org.eclipse.jface.text.IUndoManager;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.resource.IResourceDescription;
import org.eclipse.xtext.resource.IResourceServiceProvider;
import org.eclipse.xtext.ui.editor.XtextEditor;
import org.eclipse.xtext.ui.editor.XtextSourceViewer;
import org.eclipse.xtext.ui.editor.model.IXtextDocument;
import org.eclipse.xtext.ui.refactoring.ui.SyncUtil;
import org.eclipse.xtext.ui.testing.AbstractEditorTest;
import org.eclipse.xtext.ui.testing.util.IResourcesSetupUtil;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

import com.google.common.collect.Iterables;
Expand Down Expand Up @@ -116,7 +123,62 @@ public void testUndoRedo() throws Exception {
.getQualifiedName().getLastSegment());
Iterables.getLast(events);
}

/*
* @see https://github.com/eclipse/xtext/issues/2385
*/
@Test public void testModifyFileInExternEditor() throws Exception {
IXtextDocument document = editor.getDocument();

Display.getDefault().readAndDispatch();

assertNotEquals(document.get(), "");

getWorkbench().getActiveWorkbenchWindow().getActivePage().getViewReferences()[0].getView(false).setFocus();

File externalEditFile = ((IFileEditorInput)editor.getEditorInput()).getFile().getLocation().toFile();
try (FileWriter fw = new FileWriter(externalEditFile)) {
fw.write("");
}
editor.setFocus();
Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_REFRESH, null);
syncUtil.yieldToQueuedDisplayJobs(new NullProgressMonitor());
syncUtil.waitForReconciler(editor);
assertEquals(document.get(), "");
}

/**
* This test needs a manual button click.
*/
@Ignore
@Test public void testModifyDirtyFileInExternEditor() throws Exception {
IXtextDocument document = editor.getDocument();

Display.getDefault().readAndDispatch();

assertNotEquals(document.get(), "");
document.set("/* Hello World! */");
assertEquals("/* Hello World! */", document.get());
assertTrue(editor.isDirty());

getWorkbench().getActiveWorkbenchWindow().getActivePage().getViewReferences()[0].getView(false).setFocus();

File externalEditFile = ((IFileEditorInput)editor.getEditorInput()).getFile().getLocation().toFile();
try (FileWriter fw = new FileWriter(externalEditFile)) {
fw.write("");
}
editor.setFocus();
// Dialog opens and the "Ignore file change" button has to be clicked.
Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_REFRESH, null);
syncUtil.yieldToQueuedDisplayJobs(new NullProgressMonitor());
syncUtil.waitForReconciler(editor);
assertEquals(document.get(), "/* Hello World! */");

assertTrue(editor.isDirty());
editor.doSave(new NullProgressMonitor());
assertFalse(editor.isDirty());
}

private IEObjectDescription getFirstExportedObjectInLastEventDelta() {
return Iterables.getFirst(Iterables.getLast(events).getDeltas().get(0).getNew().getExportedObjects(), null);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.editors.text.TextEditor;
import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.IDocumentProviderExtension3;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.texteditor.ITextEditorActionConstants;
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
Expand Down Expand Up @@ -327,6 +329,16 @@ public void doSave(IProgressMonitor progressMonitor) {
callback.afterSave(this);
}

@Override
protected void performSave(boolean overwrite, IProgressMonitor progressMonitor) {
boolean unsyncOverwrite = false;
if (getDocumentProvider() instanceof IDocumentProviderExtension3) {
unsyncOverwrite = !((IDocumentProviderExtension3)getDocumentProvider()).isSynchronized(getEditorInput());
}
super.performSave(overwrite || unsyncOverwrite, progressMonitor);
}


@Override
protected void updateState(final IEditorInput input) {
new DisplayRunnable() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.eclipse.core.filesystem.IFileInfo;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IEncodedStorage;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceStatus;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.runtime.Adapters;
Expand Down Expand Up @@ -410,6 +411,14 @@ public long getModificationStamp(Object element) {

@Override
public boolean isSynchronized(Object element) {
if (!(element instanceof IFileEditorInput)) {
return super.isSynchronized(element);
}
IFileEditorInput input = (IFileEditorInput) element;
if (input.getFile() == null) {
return super.isSynchronized(element);
}

ElementInfo info = getElementInfo(element);
long synchronizationStamp;
if (info instanceof FileInfo) {
Expand All @@ -419,7 +428,15 @@ public boolean isSynchronized(Object element) {
} else {
return super.isSynchronized(element);
}
return synchronizationStamp == getModificationStamp(element);

// Check has to fit the following method:
// org.eclipse.ui.editors.text.FileDocumentProvider.checkSynchronizationState(long, IResource)
boolean isSynchronized = synchronizationStamp == getSynchronizationStamp(input.getFile());
if (!isSynchronized) {
// checks for is sync and triggers sync if necessary
input.getFile().isSynchronized(IResource.DEPTH_ZERO);
}
return isSynchronized;
}

@Override
Expand Down

0 comments on commit be83d08

Please sign in to comment.