| /* |
| * 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. |
| */ |
| |
| /* |
| * @author max |
| */ |
| package com.intellij.codeInsight; |
| |
| import com.intellij.psi.impl.source.parsing.xml.XmlBuilder; |
| import com.intellij.psi.impl.source.parsing.xml.XmlBuilderDriver; |
| import com.intellij.testFramework.LightCodeInsightTestCase; |
| import org.jetbrains.annotations.Nullable; |
| |
| public class XmlBuilderTest extends LightCodeInsightTestCase { |
| private static class TestXmlBuilder implements XmlBuilder { |
| private final StringBuilder builder = new StringBuilder(); |
| private final StringBuilder currentPhysicalText = new StringBuilder(); |
| private final StringBuilder currentDisplayText = new StringBuilder(); |
| private final ProcessingOrder myTagProcessingOrder; |
| |
| public TestXmlBuilder(final ProcessingOrder tagsAndAttributes) { |
| myTagProcessingOrder = tagsAndAttributes; |
| } |
| |
| @Override |
| public void attribute(final CharSequence name, final CharSequence value, final int startoffset, final int endoffset) { |
| flushText(); |
| builder.append("ATT: name='").append(name).append("' value='").append(value).append("'\n"); |
| } |
| |
| @Override |
| public void endTag(final CharSequence localName, final String namespace, final int startoffset, final int endoffset) { |
| flushText(); |
| builder.append("ENDTAG: name='").append(localName).append("' namespace='").append(namespace).append("'\n"); |
| } |
| |
| @Override |
| public void doctype(@Nullable final CharSequence publicId, @Nullable final CharSequence systemId, final int startOffset, final int endOffset) { |
| } |
| |
| @Override |
| public ProcessingOrder startTag(final CharSequence localName, final String namespace, final int startoffset, final int endoffset, |
| final int headerEndOffset) { |
| flushText(); |
| builder.append("TAG: name='").append(localName).append("' namespace='").append(namespace).append("'\n"); |
| return myTagProcessingOrder; |
| } |
| |
| @Override |
| public void textElement(final CharSequence display, final CharSequence physical, final int startoffset, final int endoffset) { |
| currentPhysicalText.append(physical); |
| currentDisplayText.append(display); |
| } |
| |
| @Override |
| public void entityRef(final CharSequence ref, final int startOffset, final int endOffset) { |
| flushText(); |
| builder.append("REF: '").append(ref).append("'\n"); |
| } |
| |
| @Override |
| public void error(String message, int startOffset, int endOffset) { |
| flushText(); |
| builder.append("ERROR: '").append(message).append("'\n"); |
| } |
| |
| private void flushText() { |
| if (currentPhysicalText.length() > 0) { |
| builder.append("TEXT: '").append(currentPhysicalText).append("' DISPLAY: '").append(currentDisplayText).append("'\n"); |
| currentPhysicalText.setLength(0); |
| currentDisplayText.setLength(0); |
| } |
| } |
| |
| public String getResult() { |
| flushText(); |
| return builder.toString(); |
| } |
| } |
| |
| public void testEmptyXml() throws Exception { |
| doTest("<root/>", "TAG: name='root' namespace=''\n" + |
| "ENDTAG: name='root' namespace=''\n", XmlBuilder.ProcessingOrder.TAGS_AND_ATTRIBUTES); |
| } |
| |
| public void testRealJspx() throws Exception { |
| doTest( |
| /* Test: */ |
| "<jsp:root xmlns:jsp=\"http://java.sun.com/JSP/Page\" xmlns=\"http://www.w3.org/1999/xhtml\" version=\"2.0\"\n" + |
| " xmlns:spring=\"http://www.springframework.org/tags\" xmlns:c=\"http://java.sun.com/jsp/jstl/core\">\n" + |
| "<html>\n" + |
| " <c:set var=\"foo\" value=\"${1}\"/>\n" + |
| " <c:set var=\"foobar\" value=\"${2}\"/>\n" + |
| " <spring:bind path=\"test.fieldName\">\n" + |
| " <jsp:scriptlet></jsp:scriptlet>\n" + |
| " </spring:bind>\n" + |
| "</html>\n" + |
| "</jsp:root>", |
| |
| /* Expected result: */ |
| "TAG: name='root' namespace='http://java.sun.com/JSP/Page'\n" + |
| "ATT: name='xmlns:jsp' value='http://java.sun.com/JSP/Page'\n" + |
| "ATT: name='xmlns' value='http://www.w3.org/1999/xhtml'\n" + |
| "ATT: name='version' value='2.0'\n" + |
| "ATT: name='xmlns:spring' value='http://www.springframework.org/tags'\n" + |
| "ATT: name='xmlns:c' value='http://java.sun.com/jsp/jstl/core'\n" + |
| "TAG: name='html' namespace='http://www.w3.org/1999/xhtml'\n" + |
| "TAG: name='set' namespace='http://java.sun.com/jsp/jstl/core'\n" + |
| "ATT: name='var' value='foo'\n" + |
| "ATT: name='value' value='${1}'\n" + |
| "ENDTAG: name='set' namespace='http://java.sun.com/jsp/jstl/core'\n" + |
| "TAG: name='set' namespace='http://java.sun.com/jsp/jstl/core'\n" + |
| "ATT: name='var' value='foobar'\n" + |
| "ATT: name='value' value='${2}'\n" + |
| "ENDTAG: name='set' namespace='http://java.sun.com/jsp/jstl/core'\n" + |
| "TAG: name='bind' namespace='http://www.springframework.org/tags'\n" + |
| "ATT: name='path' value='test.fieldName'\n" + |
| "TAG: name='scriptlet' namespace='http://java.sun.com/JSP/Page'\n" + |
| "ENDTAG: name='scriptlet' namespace='http://java.sun.com/JSP/Page'\n" + |
| "ENDTAG: name='bind' namespace='http://www.springframework.org/tags'\n" + |
| "ENDTAG: name='html' namespace='http://www.w3.org/1999/xhtml'\n" + |
| "ENDTAG: name='root' namespace='http://java.sun.com/JSP/Page'\n", |
| XmlBuilder.ProcessingOrder.TAGS_AND_ATTRIBUTES); |
| } |
| |
| public void testRealJspxNoAttributes() throws Exception { |
| doTest( |
| /* Test: */ |
| "<jsp:root xmlns:jsp=\"http://java.sun.com/JSP/Page\" xmlns=\"http://www.w3.org/1999/xhtml\" version=\"2.0\"\n" + |
| " xmlns:spring=\"http://www.springframework.org/tags\" xmlns:c=\"http://java.sun.com/jsp/jstl/core\">\n" + |
| "<html>\n" + |
| " <c:set var=\"foo\" value=\"${1}\"/>\n" + |
| " <c:set var=\"foobar\" value=\"${2}\"/>\n" + |
| " <spring:bind path=\"test.fieldName\">\n" + |
| " <jsp:scriptlet></jsp:scriptlet>\n" + |
| " </spring:bind>\n" + |
| "</html>\n" + |
| "</jsp:root>", |
| |
| /* Expected result: */ |
| "TAG: name='root' namespace='http://java.sun.com/JSP/Page'\n" + |
| "TAG: name='html' namespace='http://www.w3.org/1999/xhtml'\n" + |
| "TAG: name='set' namespace='http://java.sun.com/jsp/jstl/core'\n" + |
| "ENDTAG: name='set' namespace='http://java.sun.com/jsp/jstl/core'\n" + |
| "TAG: name='set' namespace='http://java.sun.com/jsp/jstl/core'\n" + |
| "ENDTAG: name='set' namespace='http://java.sun.com/jsp/jstl/core'\n" + |
| "TAG: name='bind' namespace='http://www.springframework.org/tags'\n" + |
| "TAG: name='scriptlet' namespace='http://java.sun.com/JSP/Page'\n" + |
| "ENDTAG: name='scriptlet' namespace='http://java.sun.com/JSP/Page'\n" + |
| "ENDTAG: name='bind' namespace='http://www.springframework.org/tags'\n" + |
| "ENDTAG: name='html' namespace='http://www.w3.org/1999/xhtml'\n" + |
| "ENDTAG: name='root' namespace='http://java.sun.com/JSP/Page'\n", |
| XmlBuilder.ProcessingOrder.TAGS); |
| } |
| |
| |
| public void testNamespaceOverride() throws Exception { |
| doTest( |
| "<c:x xmlns:c=\"ns1\">\n" + |
| " <c:y/>\n" + |
| " <c:x xmlns:c=\"ns2\">\n" + |
| " <c:y/>\n" + |
| " </c:x>\n" + |
| " <c:y/>\n" + |
| "</c:x>\n", |
| |
| "TAG: name='x' namespace='ns1'\n" + |
| "ATT: name='xmlns:c' value='ns1'\n" + |
| "TAG: name='y' namespace='ns1'\n" + |
| "ENDTAG: name='y' namespace='ns1'\n" + |
| "TAG: name='x' namespace='ns2'\n" + |
| "ATT: name='xmlns:c' value='ns2'\n" + |
| "TAG: name='y' namespace='ns2'\n" + |
| "ENDTAG: name='y' namespace='ns2'\n" + |
| "ENDTAG: name='x' namespace='ns2'\n" + |
| "TAG: name='y' namespace='ns1'\n" + |
| "ENDTAG: name='y' namespace='ns1'\n" + |
| "ENDTAG: name='x' namespace='ns1'\n", |
| XmlBuilder.ProcessingOrder.TAGS_AND_ATTRIBUTES); |
| } |
| |
| public void testSimpleEntityResolution() throws Exception { |
| doTest( |
| "<root><</root>", |
| "TAG: name='root' namespace=''\n" + |
| "TEXT: '<' DISPLAY: '<'\n" + |
| "ENDTAG: name='root' namespace=''\n", |
| XmlBuilder.ProcessingOrder.TAGS_AND_TEXTS); |
| } |
| |
| public void testCDATA() throws Exception { |
| doTest( |
| "<root><![CDATA[<asis/>]]></root>", |
| "TAG: name='root' namespace=''\n" + |
| "TEXT: '<![CDATA[<asis/>]]>' DISPLAY: '<asis/>'\n" + |
| "ENDTAG: name='root' namespace=''\n", |
| XmlBuilder.ProcessingOrder.TAGS_AND_TEXTS |
| ); |
| } |
| |
| public void testErrors() throws Exception { |
| doTest( |
| "<root>" + |
| "<foo>" + |
| "<bar" + |
| "<" + |
| "</root>", |
| "TAG: name='root' namespace=''\n" + |
| "TAG: name='foo' namespace=''\n" + |
| "ERROR: 'Element foo is not closed'\n" + |
| "ENDTAG: name='foo' namespace=''\n" + |
| "TAG: name='bar' namespace=''\n" + |
| "ERROR: 'Tag start is not closed'\n" + |
| "ENDTAG: name='bar' namespace=''\n" + |
| "TAG: name='' namespace=''\n" + |
| "ERROR: 'Tag name expected'\n" + |
| "ENDTAG: name='' namespace=''\n" + |
| "ENDTAG: name='root' namespace=''\n", |
| XmlBuilder.ProcessingOrder.TAGS_AND_TEXTS |
| ); |
| } |
| |
| public void testComments() throws Exception { |
| doTest( |
| "<root>" + |
| "<foo>" + |
| "<!--aa-->" + |
| "</foo>" + |
| "<foo>" + |
| "<!---->" + |
| "</foo>" + |
| "<foo>" + |
| "aaa<!--aa-->aaa" + |
| "</foo>" + |
| "<foo>" + |
| "\naaa\n<!--aa-->\naaa\n" + |
| "</foo>" + |
| "</root>", |
| "TAG: name='root' namespace=''\n" + |
| "TAG: name='foo' namespace=''\n" + |
| "ENDTAG: name='foo' namespace=''\n" + |
| "TAG: name='foo' namespace=''\n" + |
| "ENDTAG: name='foo' namespace=''\n" + |
| "TAG: name='foo' namespace=''\n" + |
| "TEXT: 'aaaaaa' DISPLAY: 'aaaaaa'\n" + |
| "ENDTAG: name='foo' namespace=''\n" + |
| "TAG: name='foo' namespace=''\n" + |
| "TEXT: '\naaa\n\naaa\n' DISPLAY: '\naaa\n\naaa\n'\n" + |
| "ENDTAG: name='foo' namespace=''\n" + |
| "ENDTAG: name='root' namespace=''\n", |
| XmlBuilder.ProcessingOrder.TAGS_AND_TEXTS |
| ); |
| } |
| |
| private static void doTest(String xml, String expectedEventSequence, final XmlBuilder.ProcessingOrder tagsAndAttributes) { |
| final TestXmlBuilder builder = new TestXmlBuilder(tagsAndAttributes); |
| new XmlBuilderDriver(xml).build(builder); |
| assertEquals(expectedEventSequence, builder.getResult()); |
| } |
| } |