| /* |
| * 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.UndoConfirmationPolicy; |
| import com.intellij.openapi.command.WriteCommandAction; |
| import com.intellij.openapi.editor.Document; |
| import com.intellij.openapi.editor.RangeMarker; |
| import com.intellij.openapi.fileTypes.StdFileTypes; |
| import com.intellij.openapi.util.TextRange; |
| import com.intellij.openapi.util.io.FileUtil; |
| import com.intellij.openapi.vfs.VfsUtil; |
| import com.intellij.openapi.vfs.VirtualFileManager; |
| import com.intellij.psi.*; |
| import com.intellij.psi.codeStyle.CodeStyleManager; |
| import com.intellij.psi.xml.*; |
| import com.intellij.testFramework.LightCodeInsightTestCase; |
| import com.intellij.util.ArrayUtil; |
| import com.intellij.util.IncorrectOperationException; |
| import com.intellij.util.LocalTimeCounter; |
| import com.intellij.xml.util.XmlTagUtil; |
| |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.net.MalformedURLException; |
| import java.util.Arrays; |
| |
| /** |
| * @author peter |
| */ |
| @SuppressWarnings({"ConstantConditions", "EmptyCatchBlock"}) |
| public class XmlTagTest extends LightCodeInsightTestCase { |
| private static XmlTag createTag(String value) throws IncorrectOperationException { |
| return XmlElementFactory.getInstance(getProject()).createTagFromText("<foo>" + value + "</foo>"); |
| } |
| |
| public void testGetTextValue() throws Throwable { |
| assertEquals("bar", createTag("bar").getValue().getText()); |
| } |
| |
| public void testCharRefs() throws Throwable { |
| String[] names = XmlTagUtil.getCharacterEntityNames(); |
| for (String name : names) { |
| XmlTag tag = createTag("foo&" + name + ";bar"); |
| assertEquals("foo" + XmlTagUtil.getCharacterByEntityName(name) + "bar", tag.getValue().getTrimmedText()); |
| } |
| } |
| |
| public void testLocalNSDeclarations() throws Throwable { |
| final XmlTag tag = XmlElementFactory.getInstance(getProject()).createTagFromText("<foo xmlns='aaa' xmlns:a='bbbb'/>"); |
| final Object[] nsPrefixes = ArrayUtil.toObjectArray(tag.getLocalNamespaceDeclarations().keySet()); |
| Arrays.sort(nsPrefixes); |
| assertEquals(2, nsPrefixes.length); |
| assertEquals("a",nsPrefixes[1]); |
| assertEquals("",nsPrefixes[0]); |
| } |
| |
| public void testCDATA() throws Throwable { |
| XmlTag tag = createTag("foo<![CDATA[<>&'\"]]>bar"); |
| assertEquals("foo<>&'\"bar", tag.getValue().getTrimmedText()); |
| } |
| |
| public void testWhitespacesInAttributes() throws Throwable { |
| XmlTag tag = XmlElementFactory.getInstance(getProject()).createTagFromText("<a c=d>b</a>"); |
| assertEquals("b", tag.getValue().getText()); |
| } |
| |
| public void testCreateChildTag() throws Throwable { |
| final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<a xmlns=\"aNamespace\"/>"); |
| final XmlTag childTag = rootTag.createChildTag("b", "bNamespace", null, true); |
| assertEquals("bNamespace", childTag.getNamespace()); |
| |
| WriteCommandAction.runWriteCommandAction(null, new Runnable() { |
| @Override |
| public void run() { |
| XmlTag beanTag = (XmlTag)rootTag.add(childTag); |
| assertEquals("bNamespace", beanTag.getNamespace()); |
| } |
| }); |
| } |
| |
| public void testDeleteTag() throws Throwable { |
| XmlTag aTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<a><b/> </a>"); |
| final XmlTag bTag = aTag.findFirstSubTag("b"); |
| WriteCommandAction.runWriteCommandAction(null, new Runnable(){ |
| @Override |
| public void run() { |
| bTag.delete(); |
| } |
| }); |
| |
| assertEquals(0, aTag.getSubTags().length); |
| } |
| |
| public void testReplaceTag() throws Throwable { |
| final XmlTag aTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<a><b/></a>"); |
| final XmlTag bTag = aTag.findFirstSubTag("b"); |
| WriteCommandAction.runWriteCommandAction(null, new Runnable(){ |
| @Override |
| public void run() { |
| PsiElement cTag = bTag.replace(XmlElementFactory.getInstance(getProject()).createTagFromText("<c/>")); |
| assertEquals(1, aTag.getSubTags().length); |
| assertEquals(cTag, aTag.getSubTags()[0]); |
| } |
| }); |
| } |
| |
| public void testAddText() throws Exception{ |
| final XmlElementFactory elementFactory = XmlElementFactory.getInstance(getProject()); |
| final XmlTag aTag = elementFactory.createTagFromText("<a>1</a>"); |
| final XmlText displayText = elementFactory.createDisplayText("2"); |
| |
| WriteCommandAction.runWriteCommandAction(null, new Runnable(){ |
| @Override |
| public void run() { |
| final PsiElement psiElement = aTag.addAfter(displayText, aTag.getValue().getChildren()[0]); |
| assertEquals(psiElement.getContainingFile(), aTag.getContainingFile()); |
| } |
| }); |
| } |
| |
| public void testWhitespaceInsideTag() throws Exception { |
| WriteCommandAction.runWriteCommandAction(null, new Runnable(){ |
| @Override |
| public void run() { |
| XmlElementFactory.getInstance(getProject()).createTagFromText("<p/>").getValue().setText("\n"); |
| } |
| }); |
| } |
| |
| public void testSetAttribute_ForXhtml() throws Exception { |
| XmlFile xhtmlFile = (XmlFile)PsiFileFactory.getInstance(getProject()).createFileFromText("dummy.xhtml", "<html/>"); |
| final XmlTag rootTag = xhtmlFile.getDocument().getRootTag(); |
| |
| WriteCommandAction.runWriteCommandAction(null, new Runnable(){ |
| @Override |
| public void run() { |
| rootTag.setAttribute("foo", "bar"); |
| } |
| }); |
| |
| assertEquals(1, rootTag.getAttributes().length); |
| assertEquals("bar", rootTag.getAttributeValue("foo")); |
| assertEquals("foo", rootTag.getAttributes()[0].getName()); |
| } |
| |
| public void testSetAttribute() throws Exception { |
| final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<html/>"); |
| WriteCommandAction.runWriteCommandAction(null, new Runnable(){ |
| @Override |
| public void run() { |
| rootTag.setAttribute("foo", "bar"); |
| } |
| }); |
| |
| assertEquals(1, rootTag.getAttributes().length); |
| assertEquals("bar", rootTag.getAttributeValue("foo")); |
| assertEquals("foo", rootTag.getAttributes()[0].getName()); |
| assertEquals("<html foo=\"bar\"/>", rootTag.getText()); |
| } |
| |
| public void testSetAttributeWithQuotes() throws Exception { |
| final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<html/>"); |
| final String value = "a \"b\" c"; |
| WriteCommandAction.runWriteCommandAction(null, new Runnable(){ |
| @Override |
| public void run() { |
| rootTag.setAttribute("foo", value); |
| } |
| }); |
| |
| assertEquals(1, rootTag.getAttributes().length); |
| assertEquals(value, rootTag.getAttributeValue("foo")); |
| assertEquals("foo", rootTag.getAttributes()[0].getName()); |
| assertEquals("<html foo='" + value + "'/>", rootTag.getText()); |
| } |
| |
| public void testSetAttributeWithQuotes2() throws Exception { |
| final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<html/>"); |
| final String value = "'a \"b\" c'"; |
| WriteCommandAction.runWriteCommandAction(null, new Runnable(){ |
| @Override |
| public void run() { |
| rootTag.setAttribute("foo", value); |
| } |
| }); |
| |
| final String expected = value.replaceAll("\"", """); |
| assertEquals(1, rootTag.getAttributes().length); |
| assertEquals(expected, rootTag.getAttributeValue("foo")); |
| assertEquals(value, rootTag.getAttribute("foo").getDisplayValue()); |
| assertEquals("foo", rootTag.getAttributes()[0].getName()); |
| assertEquals("<html foo=\"" + expected + "\"/>", rootTag.getText()); |
| } |
| |
| public void testSetAttributeUpdateText() throws Exception { |
| final String value = "a \"b\" c"; |
| final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<html foo='" + value + "'/>"); |
| |
| assertEquals(1, rootTag.getAttributes().length); |
| assertEquals(value, rootTag.getAttributeValue("foo")); |
| |
| final XmlAttribute foo = rootTag.getAttribute("foo"); |
| final String text = foo.getValueElement().getText(); |
| assertEquals("'" + value + "'", text); |
| |
| ((PsiLanguageInjectionHost)foo.getValueElement()).updateText(text); |
| assertEquals("<html foo='" + value + "'/>", rootTag.getText()); |
| } |
| |
| public void testSetAttributeWithNamespaces() throws Exception { |
| final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<ns:tag xmlns:ns=\"xxx\"/>"); |
| WriteCommandAction.runWriteCommandAction(null, new Runnable(){ |
| @Override |
| public void run() { |
| rootTag.setAttribute("foo", "", "bar"); |
| } |
| }); |
| |
| assertEquals(2, rootTag.getAttributes().length); |
| assertEquals("bar", rootTag.getAttributeValue("foo")); |
| assertEquals("foo", rootTag.getAttributes()[1].getName()); |
| assertEquals("<ns:tag xmlns:ns=\"xxx\" foo=\"bar\"/>", rootTag.getText()); |
| } |
| |
| public void testTextEdit1() throws Exception { |
| final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<html>aaa</html>"); |
| final XmlText xmlText = rootTag.getValue().getTextElements()[0]; |
| WriteCommandAction.runWriteCommandAction(null, new Runnable(){ |
| @Override |
| public void run() { |
| xmlText.removeText(0, 3); |
| } |
| }); |
| |
| assertEquals("<html></html>", rootTag.getText()); |
| } |
| |
| public void testTextEdit2() throws Exception { |
| final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<html>a<a</html>"); |
| WriteCommandAction.runWriteCommandAction(null, new Runnable(){ |
| @Override |
| public void run() { |
| rootTag.getValue().getTextElements()[0].removeText(0, 3); |
| } |
| }); |
| |
| assertEquals("<html></html>", rootTag.getText()); |
| } |
| |
| public void testTextEdit3() throws Exception { |
| final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<html>a<a</html>"); |
| final XmlText xmlText = rootTag.getValue().getTextElements()[0]; |
| WriteCommandAction.runWriteCommandAction(null, new Runnable(){ |
| @Override |
| public void run() { |
| xmlText.removeText(1, 2); |
| } |
| }); |
| |
| assertEquals(1, xmlText.getChildren().length); |
| assertEquals("<html>aa</html>", rootTag.getText()); |
| } |
| |
| public void testTextEdit4() throws Exception { |
| final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<html>aaa</html>"); |
| final XmlText xmlText = rootTag.getValue().getTextElements()[0]; |
| WriteCommandAction.runWriteCommandAction(null, new Runnable(){ |
| @Override |
| public void run() { |
| xmlText.removeText(1, 2); |
| } |
| }); |
| |
| assertEquals(1, xmlText.getChildren().length); |
| assertEquals("<html>aa</html>", rootTag.getText()); |
| } |
| |
| public void testTextEdit5() throws Exception { |
| final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<html><x>xxx</x>\n<y>yyy</y></html>"); |
| final XmlTag y = rootTag.findFirstSubTag("y"); |
| |
| final PsiFile file = y.getContainingFile(); |
| String text = y.getValue().getText(); |
| TextRange textRange = y.getValue().getTextRange(); |
| |
| assertEquals(text, textRange.substring(file.getText())); |
| |
| new WriteCommandAction(getProject(), file) { |
| @Override |
| protected void run(final Result result) throws Throwable { |
| CodeStyleManager.getInstance(getProject()).adjustLineIndent(file, y.getTextOffset()); |
| } |
| }.execute(); |
| |
| text = y.getValue().getText(); |
| textRange = y.getValue().getTextRange(); |
| |
| assertEquals(text, textRange.substring(file.getText())); |
| } |
| |
| public void testTextEdit6() throws Exception { |
| final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<html>a<b>1</b>c</html>"); |
| final XmlTag xmlTag = rootTag.findFirstSubTag("b"); |
| WriteCommandAction.runWriteCommandAction(null, new Runnable(){ |
| @Override |
| public void run() { |
| xmlTag.delete(); |
| } |
| }); |
| |
| assertEquals("<html>ac</html>", rootTag.getText()); |
| } |
| |
| public void testBrace() throws Exception { |
| final XmlTag tagFromText = XmlElementFactory.getInstance(getProject()).createTagFromText("<a/>"); |
| WriteCommandAction.runWriteCommandAction(null, new Runnable(){ |
| @Override |
| public void run() { |
| tagFromText.getValue().setText("<"); |
| } |
| }); |
| |
| assertEquals("<", tagFromText.getValue().getTextElements()[0].getValue()); |
| } |
| |
| public void testEmptyTextRange() throws Exception { |
| final String text = "<a></a>"; |
| final String name = "test.xhtml"; |
| XmlTag rootTag = createTag(name, text); |
| TextRange textRange = rootTag.getValue().getTextRange(); |
| assertEquals(3, textRange.getStartOffset()); |
| assertEquals(3, textRange.getEndOffset()); |
| } |
| |
| public void testDeleteTagBetweenText() throws Exception { |
| final XmlTag tag = createTag("foo.xhtml", "<p>a<div/>b</p>"); |
| final XmlTag div = tag.getSubTags()[0]; |
| new WriteCommandAction(getProject(), tag.getContainingFile()) { |
| @Override |
| protected void run(final Result result) throws Throwable { |
| div.delete(); |
| } |
| }.execute(); |
| assertEquals("<p>ab</p>", tag.getText()); |
| } |
| |
| private static XmlTag createTag(final String name, final String text) { |
| final XmlFile file = (XmlFile)PsiFileFactory.getInstance(getProject()) |
| .createFileFromText(name, StdFileTypes.XML, text, LocalTimeCounter.currentTime(), true); |
| return file.getDocument().getRootTag(); |
| } |
| |
| // tests whether rangemarker gets changed when texts are merged, passes |
| public void testRangeMarker1() throws IOException, IncorrectOperationException { |
| final XmlFile file = (XmlFile)createFile("file.xhtml", "<a>1234<b></b>567</a>"); |
| final XmlTag root = file.getDocument().getRootTag(); |
| final XmlTag tag = root.findFirstSubTag("b"); |
| |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { |
| @Override |
| public void run() { |
| final int offset = tag.getTextOffset(); |
| |
| Document document = PsiDocumentManager.getInstance(getProject()).getDocument(root.getContainingFile()); |
| RangeMarker marker = document.createRangeMarker(offset - 3, offset); |
| tag.delete(); |
| |
| |
| assertEquals(4, marker.getStartOffset()); |
| assertEquals(7, marker.getEndOffset()); |
| } |
| }, "", null); |
| } |
| }); |
| } |
| |
| // this one fails, the difference is that we do some manipulations before: move "234" before the tag |
| public void testRangeMarker2() throws IOException, IncorrectOperationException { |
| final XmlTag root = createTag("file.xhtml", "<a>1<b>234</b>567</a>"); |
| final XmlTag tag = root.findFirstSubTag("b"); |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { |
| @Override |
| public void run() { |
| Document document = PsiDocumentManager.getInstance(getProject()).getDocument(root.getContainingFile()); |
| XmlTagChild child = tag.getValue().getChildren()[0]; |
| assertTrue(child instanceof XmlText && child.getText().equals("234")); |
| |
| try { |
| tag.getParent().addBefore(child, tag); |
| |
| assertEquals(7, tag.getTextOffset()); |
| RangeMarker marker = document.createRangeMarker(4, 7); |
| tag.delete(); |
| |
| assertEquals(4, marker.getStartOffset()); |
| assertEquals(7, marker.getEndOffset()); |
| |
| } |
| catch (IncorrectOperationException e) { |
| } |
| } |
| }, "", null); |
| } |
| }); |
| } |
| |
| // the previous test relveals one problem with text merge, "234" in fact is not merged with "1" |
| public void test3() throws IOException, IncorrectOperationException { |
| final XmlTag root = XmlElementFactory.getInstance(getProject()).createTagFromText("<a>1<b>234</b>456</a>"); |
| final XmlTag tag = root.findFirstSubTag("b"); |
| |
| final XmlTagChild child = tag.getValue().getChildren()[0]; |
| assertTrue(child instanceof XmlText && child.getText().equals("234")); |
| |
| WriteCommandAction.runWriteCommandAction(null, new Runnable(){ |
| @Override |
| public void run() { |
| assertNotNull(tag.getParent().addBefore(child, tag)); |
| tag.delete(); |
| } |
| }); |
| |
| |
| assertEquals(1, root.getValue().getChildren().length); |
| assertEquals("1234456", root.getValue().getChildren()[0].getText()); |
| } |
| |
| public void test3XHTML() throws IOException, IncorrectOperationException { |
| final XmlTag root = XmlElementFactory.getInstance(getProject()).createXHTMLTagFromText("<a>1<b>234</b>456</a>"); |
| final XmlTag tag = root.findFirstSubTag("b"); |
| |
| final XmlTagChild child = tag.getValue().getChildren()[0]; |
| assertTrue(child instanceof XmlText && child.getText().equals("234")); |
| |
| WriteCommandAction.runWriteCommandAction(null, new Runnable(){ |
| @Override |
| public void run() { |
| assertNotNull(tag.getParent().addBefore(child, tag)); |
| tag.delete(); |
| } |
| }); |
| |
| |
| assertEquals(1, root.getValue().getChildren().length); |
| assertEquals("1234456", root.getValue().getChildren()[0].getText()); |
| } |
| |
| public void testDisplayText() throws Throwable { |
| final XmlTag tag = XmlElementFactory.getInstance(getProject()).createTagFromText(" <foo/>"); |
| WriteCommandAction.runWriteCommandAction(null, new Runnable(){ |
| @Override |
| public void run() { |
| tag.add(XmlElementFactory.getInstance(getProject()).createDisplayText("aaa\nbbb")); |
| } |
| }); |
| |
| assertEquals("aaa\nbbb", tag.getValue().getTextElements()[0].getValue()); |
| } |
| |
| public void testXHTMLAddBefore1() throws Exception { |
| final XmlFile file = (XmlFile)PsiFileFactory.getInstance(getProject()).createFileFromText("test.xhtml", |
| "<a>a <b>123</b> c</a>"); |
| final XmlTag tagB = file.getDocument().getRootTag().findFirstSubTag("b"); |
| |
| final XmlTagChild[] tagElements = tagB.getValue().getChildren(); |
| final PsiElement parent = tagB.getParent(); |
| |
| WriteCommandAction.runWriteCommandAction(null, new Runnable(){ |
| @Override |
| public void run() { |
| PsiElement first = parent.addBefore(tagElements[0], tagB); |
| assertNotNull(first); |
| } |
| }); |
| } |
| |
| public void testXHTMLSetAttribute1() throws Exception { |
| new WriteCommandAction.Simple(getProject()) { |
| @Override |
| protected void run() throws Throwable { |
| final XmlFile file = (XmlFile)PsiFileFactory.getInstance(getProject()).createFileFromText("test.xhtml", "<a/>"); |
| final XmlTag tagB = file.getDocument().getRootTag(); |
| |
| tagB.setAttribute("a", ""); |
| assertEquals("<a a=\"\"/>", tagB.getText()); |
| |
| tagB.setAttribute("b", ""); |
| assertEquals("<a a=\"\" b=\"\"/>", tagB.getText()); |
| |
| tagB.setAttribute("c", ""); |
| assertEquals("<a a=\"\" b=\"\" c=\"\"/>", tagB.getText()); |
| |
| tagB.getAttributes()[1].delete(); |
| assertEquals("<a a=\"\" c=\"\"/>", tagB.getText()); |
| } |
| }.execute().throwException(); |
| } |
| |
| public void testXHTMLNbsp1() throws Exception { |
| final XmlFile file = (XmlFile)PsiFileFactory.getInstance(getProject()).createFileFromText("test.xhtml", "<a> </a>"); |
| final XmlTag tagB = file.getDocument().getRootTag(); |
| assertEquals(tagB.getValue().getTextElements().length, 1); |
| assertEquals(tagB.getValue().getTextElements()[0].getValue(), "\u00a0"); |
| } |
| |
| public void testDeleteTagWithMultilineWhitespace1() throws Exception { |
| final XmlFile file = (XmlFile)PsiFileFactory.getInstance(getProject()).createFileFromText("test.xml", |
| "<a>\n <a/>\n</a>"); |
| final XmlTag tagB = file.getDocument().getRootTag(); |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| tagB.getSubTags()[0].delete(); |
| } |
| }); |
| |
| assertEquals("<a>\n </a>", tagB.getText()); |
| } |
| |
| public void testDeleteTagWithMultilineWhitespace2() throws Exception { |
| final XmlFile file = (XmlFile)PsiFileFactory.getInstance(getProject()) |
| .createFileFromText("test.xml", "<a>\n <a>\n <b>\n hasgdgasjdgasdg asgdjhasgd</b>\n </a>\n</a>"); |
| final XmlTag tagB = file.getDocument().getRootTag(); |
| WriteCommandAction.runWriteCommandAction(null, new Runnable(){ |
| @Override |
| public void run() { |
| tagB.getSubTags()[0].getSubTags()[0].delete(); |
| } |
| }); |
| |
| assertEquals("<a>\n <a>\n </a>\n</a>", tagB.getText()); |
| } |
| |
| public void testXHTMLRangeMarkers2() throws Exception { |
| XmlTag tag = createTag("file.xhtml", "<a>xyz</a>"); |
| PsiFile psiFile = tag.getContainingFile(); |
| Document document = PsiDocumentManager.getInstance(psiFile.getProject()).getDocument(psiFile); |
| RangeMarker rangeMarker = document.createRangeMarker(5, 5); |
| final XmlText text = (XmlText) tag.getValue().getChildren()[0]; |
| |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { |
| @Override |
| public void run() { |
| try{ |
| text.removeText(2, 3); |
| } |
| catch(IncorrectOperationException ioe){} |
| } |
| }, "", null, UndoConfirmationPolicy.DO_NOT_REQUEST_CONFIRMATION); |
| } |
| }); |
| |
| assertEquals(5, rangeMarker.getStartOffset()); |
| assertEquals(5, rangeMarker.getEndOffset()); |
| } |
| |
| public void testXHTMLTextInsert() throws Exception { |
| final XmlTag tag = XmlElementFactory.getInstance(getProject()).createXHTMLTagFromText("<a>xyz</a>"); |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| tag.getValue().getTextElements()[0].insertText("<", 1); |
| } |
| }); |
| |
| assertEquals("<a>x<yz</a>", tag.getText()); |
| } |
| |
| public void testSimpleTextInsertion() throws Throwable { |
| doTestSimpleInsertion("xyz", "a"); |
| doTestSimpleInsertion(" xyz", "a"); |
| doTestSimpleInsertion("x yz", "a"); |
| doTestSimpleInsertion("xy z", "a"); |
| doTestSimpleInsertion("xyz ", "a"); |
| doTestSimpleInsertion(" xyz ", "a"); |
| doTestSimpleInsertion(" x y z ", "a"); |
| } |
| |
| public void testWhitespaceTextInsertion() throws Throwable { |
| doTestSimpleInsertion("xyz", " "); |
| } |
| |
| public void testSimpleTextDeletion() throws Throwable { |
| doTestSimpleDeletion("xyz"); |
| doTestSimpleDeletion(" xyz"); |
| doTestSimpleDeletion("x yz"); |
| doTestSimpleDeletion("xy z"); |
| doTestSimpleDeletion("xyz "); |
| doTestSimpleDeletion(" xyz "); |
| doTestSimpleDeletion(" x y z "); |
| } |
| |
| public void testWhitespaceDeletion() throws Throwable { |
| doTestSimpleDeletion(" xyz"); |
| doTestSimpleDeletion("x yz"); |
| doTestSimpleDeletion("xy z"); |
| doTestSimpleDeletion("xyz "); |
| doTestSimpleDeletion(" xyz "); |
| doTestSimpleDeletion(" x y z "); |
| } |
| |
| private static void doTestSimpleDeletion(final String text) throws IncorrectOperationException { |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| for (int i = 0; i < text.length(); i++) { |
| for (int j = i; j < text.length(); j++) { |
| XmlTag tag = XmlElementFactory.getInstance(getProject()).createXHTMLTagFromText("<a>" + text + "</a>"); |
| final PsiElement[] children = tag.getValue().getTextElements(); |
| assertEquals(1, children.length); |
| final XmlText xmlText = (XmlText)children[0]; |
| assertEquals(text, xmlText.getText()); |
| xmlText.removeText(i, j); |
| final StringBuilder expected = new StringBuilder(text); |
| expected.delete(i, j); |
| assertEquals(expected.toString(), xmlText.getValue()); |
| } |
| } |
| } |
| }); |
| } |
| |
| private static void doTestSimpleInsertion(final String text, final String textToInsert) throws IncorrectOperationException { |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| for (int i = 0; i <= text.length(); i++) { |
| XmlTag tag = XmlElementFactory.getInstance(getProject()).createXHTMLTagFromText("<a>" + text + "</a>"); |
| final PsiElement[] children = tag.getValue().getTextElements(); |
| assertEquals(1, children.length); |
| final XmlText xmlText = (XmlText)children[0]; |
| assertEquals(text, xmlText.getValue()); |
| xmlText.insertText(textToInsert, i); |
| final StringBuilder expected = new StringBuilder(text); |
| expected.insert(i, textToInsert); |
| assertEquals(expected.toString(), xmlText.getValue()); |
| } |
| } |
| }); |
| } |
| |
| public void testEscapedInsertion() throws Throwable { |
| doTestEscapedInsertion("xyz", "&"); |
| doTestEscapedInsertion("xyz", "&&"); |
| doTestEscapedInsertion("xyz", "&x&"); |
| doTestEscapedInsertion("&xyz", "a"); |
| doTestEscapedInsertion("&xyz", " "); |
| doTestEscapedInsertion("x&yz", "a"); |
| doTestEscapedInsertion("x&yz", " "); |
| doTestEscapedInsertion("xy&z", "a"); |
| doTestEscapedInsertion("xy&z", " "); |
| doTestEscapedInsertion("xyz&", "a"); |
| doTestEscapedInsertion("xyz&", " "); |
| doTestEscapedInsertion("&x&y&z&", "a"); |
| doTestEscapedInsertion(" x&y&z&", "a"); |
| doTestEscapedInsertion(" x y&z&", "a"); |
| doTestEscapedInsertion("&x y&z&", "a"); |
| doTestEscapedInsertion("&x y&z ", "a"); |
| doTestEscapedInsertion("&x&y&z&", "<"); |
| doTestEscapedInsertion("&x&y&z&", ">"); |
| doTestEscapedInsertion("_xyz", "a"); |
| doTestEscapedInsertion("x_yz", "a"); |
| doTestEscapedInsertion("xy_z", "a"); |
| doTestEscapedInsertion("xyz_", "a"); |
| doTestEscapedInsertion("_xyz_", "a"); |
| doTestEscapedInsertion("_x_y_z_", "a"); |
| } |
| |
| public static void notestEscapedDeletion() { |
| doTestEscapedDeletion("&"); |
| doTestEscapedDeletion("&&"); |
| doTestEscapedDeletion(" &&"); |
| doTestEscapedDeletion(" & &"); |
| doTestEscapedDeletion(" & & "); |
| doTestEscapedDeletion(" && "); |
| doTestEscapedDeletion("&& "); |
| doTestEscapedDeletion("& "); |
| doTestEscapedDeletion(" "); |
| doTestEscapedDeletion("&abc"); |
| doTestEscapedDeletion("a&bc"); |
| doTestEscapedDeletion("ab&c"); |
| doTestEscapedDeletion("abc&"); |
| doTestEscapedDeletion(" &abc"); |
| doTestEscapedDeletion("a &bc"); |
| doTestEscapedDeletion("ab &c"); |
| doTestEscapedDeletion("abc &"); |
| doTestEscapedDeletion("& abc"); |
| doTestEscapedDeletion("a& bc"); |
| doTestEscapedDeletion("ab& c"); |
| doTestEscapedDeletion("abc& "); |
| } |
| |
| private static void doTestEscapedInsertion(final String text, final String textToInsert) throws IncorrectOperationException { |
| String tagText = toEscapedText(text); |
| for (int i = 0; i <= text.length(); i++) { |
| XmlTag tag = XmlElementFactory.getInstance(getProject()).createXHTMLTagFromText("<a>" + tagText + "</a>"); |
| final PsiElement[] children = tag.getValue().getTextElements(); |
| assertEquals(1, children.length); |
| final XmlText xmlText = (XmlText)children[0]; |
| assertEquals(tagText, xmlText.getText()); |
| xmlText.insertText(textToInsert, i); |
| final StringBuilder expectedDisplay = new StringBuilder(text.replace('_', '\u00a0')); |
| expectedDisplay.insert(i, textToInsert); |
| assertEquals(expectedDisplay.toString(), xmlText.getValue()); |
| |
| // final String expectedText = toEscapedText(expectedDisplay.toString()); |
| // assertEquals(expectedText, xmlText.getText()); |
| } |
| } |
| |
| private static void doTestEscapedDeletion(final String text) throws IncorrectOperationException { |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| String tagText = toEscapedText(text); |
| for (int i = 0; i < text.length(); i++) { |
| for (int j = i; j < text.length(); j++) { |
| XmlTag tag = XmlElementFactory.getInstance(getProject()).createXHTMLTagFromText("<a>" + tagText + "</a>"); |
| final PsiElement[] children = tag.getValue().getTextElements(); |
| assertEquals(1, children.length); |
| final XmlText xmlText = (XmlText)children[0]; |
| assertEquals(tagText, xmlText.getText()); |
| xmlText.removeText(i, j); |
| final StringBuilder expectedDisplay = new StringBuilder(text.replace('_', ' ')); |
| expectedDisplay.delete(i, j); |
| assertEquals(expectedDisplay.toString(), xmlText.getValue()); |
| |
| final String expectedText = toEscapedText(expectedDisplay.toString()); |
| assertEquals(expectedText, xmlText.getText()); |
| } |
| } |
| } |
| }); |
| } |
| |
| public void testWhitespacesInEmptyXHTMLTag() throws Exception{ |
| final XmlTag tag = XmlElementFactory.getInstance(getProject()).createXHTMLTagFromText("<a> <b/> </a>"); |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| tag.findFirstSubTag("b").delete(); |
| } |
| }); |
| |
| assertEquals("<a> </a>", tag.getText()); |
| } |
| |
| public void test2() throws Exception { |
| XmlFile file = (XmlFile)createFile("file.xml", "<a>x y</a>"); |
| XmlTag tag = file.getDocument().getRootTag(); |
| final XmlText xmlText = tag.getValue().getTextElements()[0]; |
| |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { |
| @Override |
| public void run() { |
| try { |
| xmlText.insertText("z", 1); |
| } |
| catch (IncorrectOperationException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| }, "", null, UndoConfirmationPolicy.DO_NOT_REQUEST_CONFIRMATION); |
| } |
| }); |
| assertEquals("<a>xz y</a>", tag.getText()); |
| } |
| |
| private static String toDisplay(String text) { |
| text = text.replaceAll("<", "<"); |
| text = text.replaceAll(">", ">"); |
| text = text.replaceAll("&", "&"); |
| text = text.replaceAll("'", "'"); |
| text = text.replaceAll(""", "\""); |
| text = text.replaceAll("<!\\[CDATA\\[", ""); |
| text = text.replaceAll("\\]\\]>", ""); |
| return text.replaceAll(" ", "_"); |
| } |
| |
| private static String toEscapedText(String original) { |
| String text = original.replaceAll("<", "<"); |
| text = text.replaceAll(">", ">"); |
| text = text.replaceAll("&", "&"); |
| text = text.replaceAll("'", "'"); |
| text = text.replaceAll("\"", """); |
| text = text.replaceAll("_", " "); |
| assertEquals(original, toDisplay(text)); |
| return text; |
| } |
| |
| public void testCoordinateMappingConsistent() throws Exception { |
| doCoordinateMappingConsistentFromDisplayText("abc"); |
| doCoordinateMappingConsistentFromDisplayText(" abc"); |
| doCoordinateMappingConsistentFromDisplayText(" a bc"); |
| doCoordinateMappingConsistentFromDisplayText(" a b c"); |
| doCoordinateMappingConsistentFromDisplayText(" a b c "); |
| doCoordinateMappingConsistentFromDisplayText(" ab c "); |
| doCoordinateMappingConsistentFromDisplayText(" abc "); |
| doCoordinateMappingConsistentFromDisplayText("abc "); |
| |
| doCoordinateMappingConsistentFromDisplayText(" "); |
| doCoordinateMappingConsistentFromDisplayText("&"); |
| |
| doCoordinateMappingConsistentFromDisplayText("&abc"); |
| doCoordinateMappingConsistentFromDisplayText(" &abc"); |
| doCoordinateMappingConsistentFromDisplayText(" a& bc"); |
| doCoordinateMappingConsistentFromDisplayText(" a &b c"); |
| doCoordinateMappingConsistentFromDisplayText(" a b& c "); |
| doCoordinateMappingConsistentFromDisplayText(" ab c& "); |
| doCoordinateMappingConsistentFromDisplayText(" ab&c "); |
| doCoordinateMappingConsistentFromDisplayText("abc &"); |
| doCoordinateMappingConsistentFromDisplayText("abc&"); |
| doCoordinateMappingConsistentFromDisplayText("ab&c&"); |
| doCoordinateMappingConsistentFromDisplayText("ab&c"); |
| doCoordinateMappingConsistentFromDisplayText("a&b&c"); |
| |
| doCoordinateMappingConsistentFromEscapedText("<![CDATA[ ]]>"); |
| doCoordinateMappingConsistentFromEscapedText("<![CDATA[x]]>"); |
| doCoordinateMappingConsistentFromEscapedText("xxx<![CDATA[x]]>"); |
| doCoordinateMappingConsistentFromEscapedText("xxx<![CDATA[x]]>xxx"); |
| doCoordinateMappingConsistentFromEscapedText("xxx&<![CDATA[x]]>xxx"); |
| doCoordinateMappingConsistentFromEscapedText("xxx&<![CDATA[x]]>&xxx"); |
| doCoordinateMappingConsistentFromEscapedText("xxx<![CDATA[x]]>&xxx"); |
| doCoordinateMappingConsistentFromEscapedText("xxx<![CDATA[xas]]>&xxx"); |
| doCoordinateMappingConsistentFromEscapedText("xxx<![CDATA[xa>s]]>&xxx"); |
| doCoordinateMappingConsistentFromEscapedText("xxx<![CDATA[x<a>s]]>&xxx"); |
| } |
| |
| public void testNBSP() throws Exception { |
| final XmlTag tagA = XmlElementFactory.getInstance(getProject()).createXHTMLTagFromText("<a>1<b> </b></a>"); |
| |
| final XmlTag tagB = tagA.findFirstSubTag("b"); |
| final XmlTagChild nbsp = tagB.getValue().getChildren()[0]; |
| assertEquals(" ", nbsp.getText()); |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| tagA.addBefore(nbsp.copy(), tagB); |
| } |
| }); |
| |
| XmlTagChild nbsp1 = tagA.getValue().getChildren()[0]; |
| assertEquals("1 ", nbsp1.getText()); |
| } |
| |
| private static void doCoordinateMappingConsistentFromDisplayText(final String text) throws IncorrectOperationException { |
| doCoordinateMappingConsistentFromEscapedText(toEscapedText(text)); |
| } |
| |
| private static void doCoordinateMappingConsistentFromEscapedText(final String tagText) throws IncorrectOperationException { |
| String text = toDisplay(tagText); |
| XmlTag tag = XmlElementFactory.getInstance(getProject()).createTagFromText("<a>" + tagText + "</a>"); |
| final PsiElement[] children = tag.getValue().getTextElements(); |
| assertEquals(1, children.length); |
| final XmlText xmlText = (XmlText)children[0]; |
| assertEquals(tagText, xmlText.getText()); |
| |
| for (int i = 0; i <= text.length(); i++) { |
| final int physical = xmlText.displayToPhysical(i); |
| final int display = xmlText.physicalToDisplay(physical); |
| assertEquals("Coords mapping failed for: '" + tagText + "' - " + physical, display, i); |
| } |
| |
| assertEquals("Coords mapping failed for: '" + tagText + "'", 0, xmlText.physicalToDisplay(0)); |
| assertEquals(tagText.length(), xmlText.displayToPhysical(text.length())); |
| assertEquals(text.length(), xmlText.physicalToDisplay(tagText.length())); |
| } |
| |
| public void testStrangeCharactesInText() throws Throwable { |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| XmlElementFactory.getInstance(getProject()).createTagFromText("<a/>").getValue().setText("@#$%@$%$${${''}"); |
| } |
| }); |
| } |
| |
| public void testPsiToDocumentSynchronizationFailed() throws Throwable { |
| String text = "<wpd><methods> </methods></wpd>"; |
| final File tempFile = FileUtil.createTempFile("idea-test", ".xml"); |
| tempFile.createNewFile(); |
| final FileOutputStream fileOutputStream = new FileOutputStream(tempFile); |
| fileOutputStream.write(text.getBytes()); |
| fileOutputStream.flush(); |
| fileOutputStream.close(); |
| |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { |
| @Override |
| @SuppressWarnings({"ConstantConditions"}) |
| public void run() { |
| VirtualFileManager.getInstance().syncRefresh(); |
| XmlFile file ;//createTemporaryFile("wpd.xml", text)); |
| try { |
| file = (XmlFile)getPsiManager().findFile(VfsUtil.findFileByURL(tempFile.toURL())); |
| } |
| catch (MalformedURLException e) { |
| throw new RuntimeException(e); |
| } |
| |
| final XmlTag methodTag = file.getDocument().getRootTag().findFirstSubTag("methods"); |
| try { |
| methodTag.add(XmlElementFactory.getInstance(getProject()).createTagFromText("<method/>")); |
| } |
| catch (IncorrectOperationException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| }, "", null, UndoConfirmationPolicy.DO_NOT_REQUEST_CONFIRMATION); |
| } |
| }); |
| } |
| |
| public void testXmlFormattingException() throws Throwable { |
| final XmlTag tag = XmlElementFactory.getInstance(getProject()).createTagFromText("<foo>bar</foo>"); |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| tag.add(XmlElementFactory.getInstance(getProject()).createTagFromText("<bar/>")); |
| } |
| }); |
| } |
| |
| public void testSetNamespace() throws Exception { |
| XmlFile xhtmlFile = (XmlFile)PsiFileFactory.getInstance(getProject()).createFileFromText("dummy.xml", |
| "<html><body/></html>"); |
| |
| final XmlTag rootTag = xhtmlFile.getDocument().getRootTag(); |
| |
| rootTag.getSubTags()[0].getNamespace(); // fill the cache |
| |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| rootTag.setAttribute("xmlns", "http://www.ru"); |
| } |
| }); |
| |
| assertEquals("http://www.ru", rootTag.getSubTags()[0].getNamespace()); |
| } |
| |
| public void testInsert() throws Exception { |
| String html = "<html><head /><body><hr /></body>\n</html>"; |
| XmlFile file = (XmlFile)PsiFileFactory.getInstance(getProject()).createFileFromText("xxx.xhtml", html); |
| XmlTag body = file.getDocument().getRootTag().findFirstSubTag("body"); |
| final XmlTag hr = body.getSubTags()[0]; |
| |
| final XmlText text = XmlElementFactory.getInstance(getProject()).createDisplayText("p"); |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| PsiElement element = hr.getParentTag().addAfter(text, hr); |
| assertEquals(element.getParent(), hr.getParentTag()); |
| } |
| }); |
| } |
| |
| public void testCollapse() throws IncorrectOperationException { |
| final XmlTag tag = XmlElementFactory.getInstance(getProject()).createTagFromText("<foo></foo>"); |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| tag.collapseIfEmpty(); |
| assertEquals("<foo/>", tag.getText()); |
| |
| final XmlTag tag1 = XmlElementFactory.getInstance(getProject()).createTagFromText("<foo>abc</foo>"); |
| tag1.collapseIfEmpty(); |
| assertEquals("<foo/>", tag1.getText()); |
| |
| final XmlTag tag2 = XmlElementFactory.getInstance(getProject()).createTagFromText("<foo><boo/></foo>"); |
| tag2.collapseIfEmpty(); |
| assertEquals("<foo><boo/></foo>", tag2.getText()); |
| } |
| }); |
| } |
| } |