blob: 049cc14ed86406609db4dfce4856db5f18800462 [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.PomManager;
import com.intellij.pom.PomModel;
import com.intellij.pom.PomModelAspect;
import com.intellij.pom.event.PomChangeSet;
import com.intellij.pom.event.PomModelEvent;
import com.intellij.pom.event.PomModelListener;
import com.intellij.pom.xml.XmlAspect;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PsiFileImpl;
import com.intellij.psi.xml.*;
import com.intellij.testFramework.LightCodeInsightTestCase;
import com.intellij.testFramework.PlatformTestUtil;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.FileNotFoundException;
public class XmlEventsTest extends LightCodeInsightTestCase {
public void test1() throws Exception{
final Listener listener = addPomListener();
final XmlTag tagFromText = XmlElementFactory.getInstance(getProject()).createTagFromText("<a/>");
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
tagFromText.setAttribute("a", "b");
}
});
assertFileTextEquals(getTestName(false) + ".txt", listener.getEventString());
}
private Listener addPomListener() {
final PomModel model = PomManager.getModel(getProject());
final Listener listener = new Listener(model.getModelAspect(XmlAspect.class));
model.addModelListener(listener,myTestRootDisposable);
return listener;
}
public void test2() throws Exception{
final Listener listener = addPomListener();
final XmlTag tagFromText = XmlElementFactory.getInstance(getProject()).createTagFromText("<a>aaa</a>");
final XmlTag otherTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<a/>");
final XmlText xmlText = tagFromText.getValue().getTextElements()[0];
WriteCommandAction.runWriteCommandAction(null, new Runnable(){
@Override
public void run() {
xmlText.insertAtOffset(otherTag, 2);
}
});
assertFileTextEquals(getTestName(false) + ".txt", listener.getEventString());
}
public void test3() throws Exception{
final Listener listener = addPomListener();
final XmlTag tagFromText = XmlElementFactory.getInstance(getProject()).createTagFromText("<a>aaa</a>");
final XmlText xmlText = tagFromText.getValue().getTextElements()[0];
WriteCommandAction.runWriteCommandAction(null, new Runnable(){
@Override
public void run() {
xmlText.insertText("bb", 2);
}
});
assertFileTextEquals(getTestName(false) + ".txt", listener.getEventString());
}
public void test4() throws Exception{
final Listener listener = addPomListener();
final XmlTag tagFromText = XmlElementFactory.getInstance(getProject()).createTagFromText("<a>a </a>");
WriteCommandAction.runWriteCommandAction(null, new Runnable(){
@Override
public void run() {
tagFromText.addAfter(tagFromText.getValue().getTextElements()[0], tagFromText.getValue().getTextElements()[0]);
}
});
assertFileTextEquals(getTestName(false) + ".txt", listener.getEventString());
}
public void test5() throws Exception{
final Listener listener = addPomListener();
final XmlTag tagFromText = XmlElementFactory.getInstance(getProject()).createTagFromText("<a>aaa</a>");
WriteCommandAction.runWriteCommandAction(null, new Runnable(){
@Override
public void run() {
tagFromText.delete();
}
});
assertFileTextEquals(getTestName(false) + ".txt", listener.getEventString());
}
public void testBulkUpdate() throws Exception{
final Listener listener = addPomListener();
final PsiFile file = createFile("a.xml", "<a/>");
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
final Document document = PsiDocumentManager.getInstance(getProject()).getDocument(file);
((DocumentEx)document).setInBulkUpdate(true);
document.insertString(0, " ");
commitDocument(document);
((DocumentEx)document).setInBulkUpdate(false);
}
}.execute();
assertFileTextEquals(getTestName(false) + ".txt", listener.getEventString());
}
public void testDocumentChange1() throws Exception{
final String rootTagText = "<a/>";
final String stringToInsert = "b=\"c\"";
final int positionToInsert = 2;
checkEventsByDocumentChange(rootTagText, positionToInsert, stringToInsert);
}
public void testDocumentChange2() throws Exception{
final String rootTagText = "<a />";
final String stringToInsert = "b=\"c\"";
final int positionToInsert = 3;
checkEventsByDocumentChange(rootTagText, positionToInsert, stringToInsert);
}
public void testDocumentChange3() throws Exception{
final String rootTagText = "<b><a /></b>";
final String stringToInsert = "b=\"c\"";
final int positionToInsert = 6;
checkEventsByDocumentChange(rootTagText, positionToInsert, stringToInsert);
}
public void testAttributeValueReplace() throws Exception {
final String text = "<target name=\"old\"/>";
final Listener listener = addPomListener();
final XmlTag tag = XmlElementFactory.getInstance(getProject()).createTagFromText(text);
final XmlAttribute attribute = tag.getAttribute("name", null);
assert attribute != null;
WriteCommandAction.runWriteCommandAction(null, new Runnable(){
@Override
public void run() {
attribute.setValue("new");
}
});
assertEquals(attribute.getValue(), "new");
assertEquals("(Attribute \"name\" for tag \"target\" set to \"\"new\"\")\n", listener.getEventString());
}
private void checkEventsByDocumentChange(final String rootTagText, final int positionToInsert, final String stringToInsert)
throws Exception {
final Listener listener = addPomListener();
final XmlTag tagFromText = ((XmlFile)createFile("file.xml", rootTagText)).getDocument().getRootTag();
final PsiFileImpl containingFile = (PsiFileImpl)tagFromText.getContainingFile();
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(getProject());
final Document document = documentManager.getDocument(containingFile);
WriteCommandAction.runWriteCommandAction(null, new Runnable(){
@Override
public void run() {
document.insertString(positionToInsert, stringToInsert);
documentManager.commitDocument(document);
}
});
assertFileTextEquals(getTestName(false) + ".txt", listener.getEventString());
}
private static class Listener implements PomModelListener{
private final XmlAspect myAspect;
private final StringBuffer myBuffer = new StringBuffer();
public Listener(XmlAspect modelAspect) {
myAspect = modelAspect;
}
@Override
public void modelChanged(PomModelEvent event) {
final PomChangeSet changeSet = event.getChangeSet(myAspect);
if(changeSet == null) return;
myBuffer.append(changeSet);
myBuffer.append("\n");
}
@Override
public boolean isAspectChangeInteresting(PomModelAspect aspect) {
return aspect == myAspect;
}
String getEventString(){
return myBuffer.toString();
}
}
private static void assertFileTextEquals(String targetDataName, String treeText) throws Exception {
String fullName = PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/')+ "/xml/tests/testData/psi/events" + File.separatorChar + targetDataName;
try{
String expectedText = loadFile(fullName);
assertEquals(expectedText.trim(), treeText.trim());
}
catch(FileNotFoundException e){
//FileUtil.writeToFile(new File(fullName), StringUtil.convertLineSeparators(treeText).getBytes("UTF-8"));
fail("No output file found. Created file "+fullName);
}
}
protected static String loadFile(String fullName) throws Exception {
String text = FileUtil.loadFile(new File(fullName)).trim();
text = StringUtil.convertLineSeparators(text);
return text;
}
public void testDocumentChange() throws Exception {
final String xml = "" +
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
"<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
" android:layout_height=\"fill_parent\">\n" +
" <include layout=\"@layout/colorstrip\" />\n" +
"\n" +
"\n" +
" <LinearLayout\n" +
" android:id=\"@+id/noteArea\"\n" +
" android:layout_width=\"fill_parent\"\n" +
" android:layout_height=\"wrap_content\"\n" +
" android:layout_weight=\"1\"\n" +
" android:layout_margin=\"5dip\">\n" +
" </LinearLayout>\n" +
"\n" +
"</LinearLayout>\n";
PsiFile file = createFile("file.xml", xml);
assertTrue(file instanceof XmlFile);
XmlDocument xmlDocument = ((XmlFile)file).getDocument();
assertNotNull(xmlDocument);
final XmlTag tagFromText = xmlDocument.getRootTag();
assertNotNull(tagFromText);
final PsiFileImpl containingFile = (PsiFileImpl)tagFromText.getContainingFile();
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(getProject());
final Document document = documentManager.getDocument(containingFile);
assertNotNull(document);
final TestListener listener = new TestListener();
PsiManager.getInstance(getProject()).addPsiTreeChangeListener(listener);
CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() {
@Override
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
int positionToInsert = xml.indexOf(" <LinearLayout\n" +
" android:id=\"@+id/noteArea\"\n");
assertFalse(positionToInsert == -1);
String stringToInsert = "<Button android:id=\"@+id/newid\" />\n";
document.insertString(positionToInsert, stringToInsert);
documentManager.commitDocument(document);
}
});
}
}, "", null);
PsiManager.getInstance(getProject()).removePsiTreeChangeListener(listener);
}
private static class TestListener extends PsiTreeChangeAdapter {
@Override
public void childReplaced(@NotNull PsiTreeChangeEvent event) {
if (event.getNewChild() != null) {
assertNotSame("Received identical before and after children in childReplaced;", event.getOldChild(), event.getNewChild());
}
}
}
}