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 Sep 3, 2024
1 parent 197f6cc commit 9ef866f
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,36 @@
*/
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.ui.editors.text.FileDocumentProvider;
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 +124,68 @@ 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(), "");
assertTrue(editor.getDocumentProvider() instanceof FileDocumentProvider);

FileDocumentProvider fileDocumentProvider = (FileDocumentProvider)editor.getDocumentProvider();

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);

assertTrue(fileDocumentProvider.isSynchronized(editor.getEditorInput()));

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,20 @@ public void doSave(IProgressMonitor progressMonitor) {
callback.afterSave(this);
}

@Override
protected void performSave(boolean overwrite, IProgressMonitor progressMonitor) {
super.performSave(overwrite || isSynchronized(), progressMonitor);
}


private boolean isSynchronized() {
IResource resource = getResource();
if (resource != null) {
return resource.isSynchronized(IResource.DEPTH_ZERO);
}
return false;
}

@Override
protected void updateState(final IEditorInput input) {
new DisplayRunnable() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -408,20 +408,6 @@ public long getModificationStamp(Object element) {
}
}

@Override
public boolean isSynchronized(Object element) {
ElementInfo info = getElementInfo(element);
long synchronizationStamp;
if (info instanceof FileInfo) {
synchronizationStamp = ((FileInfo) info).fModificationStamp;
} else if (info instanceof URIInfo) {
synchronizationStamp = ((URIInfo) info).synchronizationStamp;
} else {
return super.isSynchronized(element);
}
return synchronizationStamp == getModificationStamp(element);
}

@Override
public boolean isModifiable(Object element) {
if (isWorkspaceExternalEditorInput(element)) {
Expand Down

0 comments on commit 9ef866f

Please sign in to comment.