blob: 9ee0f998b0dba71479ac4af179a4b449430a4dc9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Ed Swartz <ed.swartz@nokia.com> - initial API and implementation
* (bug 157203: [ltk] [patch] TextEditBasedChange/TextChange provides incorrect diff when one side is empty)
*******************************************************************************/
package org.eclipse.jdt.ui.tests.refactoring.changes;
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEditGroup;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IRegion;
import org.eclipse.ltk.core.refactoring.DocumentChange;
import org.eclipse.ltk.core.refactoring.TextEditChangeGroup;
/**
* Ensure that the diffs between text edits do not include
* spurious context lines when source or target regions are
* empty. Otherwise, the current content and preview content
* have differing affected ranges and spurious changes appear.
*/
public class TextDiffContentTest {
private static final String MODIFIED_SOURCE_CONTENTS =
"// my file\n"+
"\n"+
"CMyClass::CMyClass()\n"+
"\t{\n"+
"\tGoodCall();\n"+
"\tDumbCall();\n"+
"\t// [[[ begin\n"+
"\tMagicCall();\n"+
"\t// ]]] end\n"+
"\t}\n"+
"\n"+
"// other stuff\n";
private DocumentChange fDocumentChange;
private Document fDocument;
private ReplaceEdit fEdit1;
private ReplaceEdit fEdit2;
private TextEditChangeGroup fChange1;
private TextEditChangeGroup fChange2;
private ReplaceEdit fEdit3;
private TextEditChangeGroup fChange3;
@Before
public void setUp() throws Exception {
fDocument = new Document(MODIFIED_SOURCE_CONTENTS);
fDocumentChange = new DocumentChange("Changes to document", fDocument);
// store one unified change for the document
MultiTextEdit multiEdit = new MultiTextEdit();
fDocumentChange.setEdit(multiEdit);
int offset;
TextEditGroup group;
/////
offset = MODIFIED_SOURCE_CONTENTS.indexOf("\t}\n");
fEdit1 = new ReplaceEdit(
offset, 0,
"\tFinalCall();\n");
group = new TextEditGroup("Change 1");
group.addTextEdit(fEdit1);
fChange1 = new TextEditChangeGroup(fDocumentChange, group);
fDocumentChange.addTextEditChangeGroup(fChange1);
multiEdit.addChild(fEdit1);
/////
offset = 0;
fEdit2 = new ReplaceEdit(
offset, 0,
"// add comment\n");
group = new TextEditGroup("Change 2");
group.addTextEdit(fEdit2);
fChange2 = new TextEditChangeGroup(fDocumentChange, group);
fDocumentChange.addTextEditChangeGroup(fChange2);
multiEdit.addChild(fEdit2);
///
offset = MODIFIED_SOURCE_CONTENTS.indexOf("\tDumb");
int endOffset = MODIFIED_SOURCE_CONTENTS.indexOf("\t// [[[ begin", offset);
fEdit3 = new ReplaceEdit(
offset, endOffset - offset, "");
group = new TextEditGroup("Change 3");
group.addTextEdit(fEdit3);
fChange3 = new TextEditChangeGroup(fDocumentChange, group);
fDocumentChange.addTextEditChangeGroup(fChange3);
multiEdit.addChild(fEdit3);
}
private String getSource(IRegion region, int context) throws CoreException {
return fDocumentChange.getCurrentContent(region, true, context, new NullProgressMonitor());
}
private String getPreview(TextEditChangeGroup group, int context) throws CoreException {
return fDocumentChange.getPreviewContent(
new TextEditChangeGroup[] { group },
group.getRegion(), true, context, new NullProgressMonitor());
}
@Test
public void testEmptySourceRangeNoContext() throws Exception {
String src = getSource(fEdit1.getRegion(), 0);
String preview = getPreview(fChange1, 0);
assertEquals("", src);
assertEquals("\tFinalCall();", preview);
}
@Test
public void testEmptySourceRangeNoContext2() throws Exception {
String src = getSource(fEdit2.getRegion(), 0);
String preview = getPreview(fChange2, 0);
assertEquals("", src);
assertEquals("// add comment", preview);
}
@Test
public void testEmptySourceRangeContext() throws Exception {
String src = getSource(fEdit1.getRegion(), 2);
String preview = getPreview(fChange1, 2);
assertEquals("\tMagicCall();\n" +
"\t// ]]] end\n" +
"\t}\n",
src);
assertEquals(" MagicCall();\n" +
" // ]]] end\n" +
" FinalCall();\n" +
" }\n",
preview);
}
@Test
public void testEmptySourceRangeContext2() throws Exception {
String src = getSource(fEdit2.getRegion(), 2);
String preview = getPreview(fChange2, 2);
assertEquals("// my file\n",
src);
assertEquals("// add comment\n"+
"// my file\n",
preview);
}
@Test
public void testEmptyTargetRangeNoContext() throws Exception {
String src = getSource(fEdit3.getRegion(), 0);
String preview = getPreview(fChange3, 0);
assertEquals("\tDumbCall();", src);
assertEquals("", preview);
}
@Test
public void testEmptyTargetRangeContext() throws Exception {
String src = getSource(fEdit3.getRegion(), 2);
String preview = getPreview(fChange3, 2);
assertEquals("\t{\n"+"\tGoodCall();\n"+
"\tDumbCall();\n"+
"\t// [[[ begin\n"+
"\tMagicCall();",
src);
assertEquals("\t{\n"+"\tGoodCall();\n"+
"\t// [[[ begin\n"+
"\tMagicCall();",
preview);
}
}