bundle relax-ng plugin

This commit is contained in:
Eugene Kudelevsky
2010-07-11 21:03:46 +04:00
parent 35338cd62f
commit 7f86ba0ded
419 changed files with 130449 additions and 0 deletions
+1
View File
@@ -11,6 +11,7 @@
<module fileurl="file://$PROJECT_DIR$/RegExpSupport/RegExpSupport.iml" filepath="$PROJECT_DIR$/RegExpSupport/RegExpSupport.iml" />
<module fileurl="file://$PROJECT_DIR$/platform/annotations/annotations.iml" filepath="$PROJECT_DIR$/platform/annotations/annotations.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/plugins/ant/ant.iml" filepath="$PROJECT_DIR$/plugins/ant/ant.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/relaxng/relaxng.iml" filepath="$PROJECT_DIR$/plugins/relaxng/relaxng.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/platform/boot/boot.iml" filepath="$PROJECT_DIR$/platform/boot/boot.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/bootstrap/bootstrap.iml" filepath="$PROJECT_DIR$/platform/bootstrap/bootstrap.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/build/build.iml" filepath="$PROJECT_DIR$/build/build.iml" />
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+31
View File
@@ -0,0 +1,31 @@
Copyright (c) 2002, 2003 Thai Open Source Software Center Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
Neither the name of the Thai Open Source Software Center Ltd nor
the names of its contributors may be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Binary file not shown.
+56
View File
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<module relativePaths="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="lang-api" />
<orderEntry type="module" module-name="xml" />
<orderEntry type="module" module-name="dom-openapi" />
<orderEntry type="module" module-name="lang-impl" />
<orderEntry type="module" module-name="testFramework" scope="TEST" />
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/rngom-20051226-patched.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$MODULE_DIR$/lib/rngom-src.zip!/src" />
</SOURCES>
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/isorelax.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/trang-core.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/jing.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>
+13
View File
@@ -0,0 +1,13 @@
Copyright 2007 Sascha Weinreuter
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.
@@ -0,0 +1,73 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Jing Copying Conditions</title>
</head>
<body>
<h1>Jing Copying Conditions</h1>
<p>Copyright (c) 2001-2003 Thai Open Source Software Center Ltd<br />
All rights reserved.</p>
<p>Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:</p>
<ul>
<li>Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.</li>
<li>Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.</li>
<li>Neither the name of the Thai Open Source Software Center Ltd nor
the names of its contributors may be used to endorse or promote
products derived from this software without specific prior written
permission.</li>
</ul>
<p>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</p>
<h2>Third-party JARs</h2>
<p>This distribution includes some additional JAR files, which have
their own copying conditions:</p>
<dl>
<dt><code>isorelax.jar</code></dt>
<dd>Comes from <a href="http://sourceforge.net/projects/iso-relax/">ISO RELAX</a>
2003/01/08 distribution and is covered by the following license:
<p>Copyright (c) 2001-2002, SourceForge ISO-RELAX Project (ASAMI Tomoharu, Daisuke
Okajima, Kohsuke Kawaguchi, and MURATA Makoto)</p>
<p>Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</p>
<p>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</p>
<p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</p>
</dd>
</dl>
</body>
</html>
+93
View File
@@ -0,0 +1,93 @@
<idea-plugin version="2" url="http://www.jetbrains.net/confluence/display/CONTEST/RELAX-NG+Support">
<id>RelaxNG-Support</id>
<name>RELAX-NG Support</name>
<depends>com.intellij.modules.xml</depends>
<description><![CDATA[
Support for RELAX-NG XML schemas. See <a href="http://relaxng.org/">relaxng.org</a> and the corresponding
IntelliJ IDEA feature request: <a href="http://www.jetbrains.net/jira/browse/IDEA-13734">IDEA-13734</a>.
<p>
The plugin provides the following features:
</p>
<ul>
<li> Completion and validation of XML documents associated with RELAX-NG schemas</li>
<li> Editing RELAX-NG files in XML and compact syntax, including on-the-fly error checking, completion,
documentation lookup and more.</li>
<li> Conversion between different schema formats (including W3C XML Schema/XML 1.0 DTDs) using
<a href="http://www.thaiopensource.com/relaxng/trang.html">Trang</a></li>
</ul>
]]></description>
<version>1.5.5</version>
<change-notes><![CDATA[
<ul>
<li>extreme index optimization</li>
<li>renameable xml prefixes</li>
<li>IDEA 9.x compatibility bugfixes</li>
</ul>
<p>
The complete list of changes in earlier versions is available
<a href="http://www.jetbrains.net/confluence/display/CONTEST/RELAX-NG+Support#RELAX-NGSupport-VersionHistory">here</a>
</p>
]]></change-notes>
<vendor email="sascha.weinreuter@cit.de">Sascha Weinreuter</vendor>
<idea-version since-build="95.4" /><!-- 9.x -->
<extensions defaultExtensionNs="com.intellij">
<errorHandler implementation="org.intellij.plugins.relaxNG.SimpleErrorReportSubmitter" />
<gotoSymbolContributor implementation="org.intellij.plugins.relaxNG.GotoSymbolContributor" />
<xml.schemaProvider implementation="org.intellij.plugins.relaxNG.config.NoNamespaceSchemaProvider" />
<hectorComponentProvider implementation="org.intellij.plugins.relaxNG.config.NoNamespaceConfigImpl$HectorProvider" />
<fileTypeFactory implementation="org.intellij.plugins.relaxNG.compact.RncFileType$Factory" />
<completionData fileType="RNG Compact" className="org.intellij.plugins.relaxNG.compact.RncCompletionData" />
<standardResourceProvider implementation="org.intellij.plugins.relaxNG.ApplicationLoader$ResourceProvider" />
<annotator language="RELAX-NG" implementationClass="org.intellij.plugins.relaxNG.compact.ReferenceAnnotator" />
<annotator language="RELAX-NG" implementationClass="org.intellij.plugins.relaxNG.model.annotation.ModelAnnotator" />
<externalAnnotator language="RELAX-NG" implementationClass="org.intellij.plugins.relaxNG.validation.RngSchemaValidator" />
<lang.parserDefinition language="RELAX-NG" implementationClass="org.intellij.plugins.relaxNG.compact.RncParserDefinition" />
<lang.braceMatcher language="RELAX-NG" implementationClass="org.intellij.plugins.relaxNG.compact.RngCompactLanguage$MyPairedBraceMatcher" />
<lang.commenter language="RELAX-NG" implementationClass="org.intellij.plugins.relaxNG.compact.RngCompactLanguage$MyCommenter" />
<lang.foldingBuilder language="RELAX-NG" implementationClass="org.intellij.plugins.relaxNG.compact.folding.RncFoldingBuilder" />
<lang.formatter language="RELAX-NG" implementationClass="org.intellij.plugins.relaxNG.compact.formatting.RncFormattingModelBuilder" />
<lang.namesValidator language="RELAX-NG" implementationClass="org.intellij.plugins.relaxNG.compact.RngCompactLanguage$MyNamesValidator" />
<lang.syntaxHighlighterFactory key="RELAX-NG" implementationClass="org.intellij.plugins.relaxNG.compact.RngCompactLanguage$MySyntaxHighlighterFactory" />
<lang.elementManipulator forClass="org.intellij.plugins.relaxNG.compact.psi.RncFileReference" implementationClass="org.intellij.plugins.relaxNG.ProjectLoader$RncFileReferenceManipulator" />
<lang.documentationProvider language="RELAX-NG" implementationClass="org.intellij.plugins.relaxNG.compact.RngCompactLanguage$MyDocumentationProvider" />
<fileBasedIndex implementation="org.intellij.plugins.relaxNG.model.resolve.RelaxSymbolIndex" />
<include.provider implementation="org.intellij.plugins.relaxNG.model.resolve.RelaxIncludeProvider"/>
<externalAnnotator language="XML" implementationClass="org.intellij.plugins.relaxNG.validation.RngSchemaValidator" />
<lang.documentationProvider language="XML" implementationClass="org.intellij.plugins.relaxNG.RngDocumentationProvider" />
</extensions>
<project-components>
<component>
<implementation-class>org.intellij.plugins.relaxNG.ProjectLoader</implementation-class>
</component>
<component>
<interface-class>org.intellij.plugins.relaxNG.config.NoNamespaceConfig</interface-class>
<implementation-class>org.intellij.plugins.relaxNG.config.NoNamespaceConfigImpl</implementation-class>
</component>
</project-components>
<application-components>
<component>
<implementation-class>org.intellij.plugins.relaxNG.ApplicationLoader</implementation-class>
</component>
</application-components>
<actions>
<action id="ConvertSchemaAction" class="org.intellij.plugins.relaxNG.convert.ConvertSchemaAction"
text="Convert Schema..."
description="Converts the selected Schema document (RNG, RNC, XSD, DTD) into another format">
<add-to-group group-id="ToolsXmlGroup" anchor="after" relative-to-action="GenerateDTD" />
</action>
</actions>
</idea-plugin>
@@ -0,0 +1,25 @@
<html>
<head>
<style type="text/css">
body, table {
font-family: Verdana, sans-serif;
font-size: 100%;
padding-left: 2mm;
}
#footer {
font-size: 95%;
padding-top: 10px;
}
</style>
</head>
<body>
<p>
This inspections checks for any unresolved references to named patterns ("define") in a RELAX-NG file in XML Syntax.
For unresolved references, a QuickFix is offered to create a corresponding define-element.
</p>
<p id="footer">Powered by RELAX-NG Support</p>
</body>
</html>
@@ -0,0 +1,26 @@
<html>
<head>
<style type="text/css">
body, table {
font-family: Verdana, sans-serif;
font-size: 100%;
padding-left: 2mm;
}
#footer {
font-size: 95%;
padding-top: 10px;
}
</style>
</head>
<body>
<p>
This inspections checks for any unused named patterns ("define") in a RELAX-NG file (XML or Compact Syntax) and
highlights them as unused symbols. This is done with respect to includes from other files, i.e. a define is not
marked as unused if is is used through an include in another file.
</p>
<p id="footer">Powered by RELAX-NG Support</p>
</body>
</html>
@@ -0,0 +1,124 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG;
import org.intellij.plugins.relaxNG.compact.psi.impl.RncDocument;
import org.intellij.plugins.relaxNG.inspections.RngDomInspection;
import org.intellij.plugins.relaxNG.inspections.UnusedDefineInspection;
import org.intellij.plugins.relaxNG.model.descriptors.RngNsDescriptor;
import org.intellij.plugins.relaxNG.validation.ValidateAction;
import org.intellij.plugins.relaxNG.xml.dom.RngDefine;
import org.intellij.plugins.relaxNG.xml.dom.impl.RngDefineMetaData;
import com.intellij.codeInspection.InspectionToolProvider;
import com.intellij.javaee.ResourceRegistrar;
import com.intellij.javaee.StandardResourceProvider;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.psi.PsiElement;
import com.intellij.psi.filters.AndFilter;
import com.intellij.psi.filters.ClassFilter;
import com.intellij.psi.filters.ElementFilter;
import com.intellij.psi.filters.position.NamespaceFilter;
import com.intellij.psi.meta.MetaDataRegistrar;
import com.intellij.psi.xml.XmlDocument;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.xml.DomElement;
import com.intellij.util.xml.DomManager;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 18.07.2007
*/
public class ApplicationLoader implements ApplicationComponent, InspectionToolProvider {
private static final String RNG_EXT = "rng";
private static final String VALIDATE_XML = "ValidateXml";
@NonNls
@NotNull
public String getComponentName() {
return "Relax-NG";
}
public void initComponent() {
registerMetaData();
final FileTypeManager ftm = FileTypeManager.getInstance();
ftm.registerFileType(StdFileTypes.XML, RNG_EXT);
installValidateXmlAction();
}
private static void installValidateXmlAction() {
final ActionManager mgr = ActionManager.getInstance();
final AnAction validateAction = mgr.getAction(VALIDATE_XML);
mgr.unregisterAction(VALIDATE_XML);
mgr.registerAction(VALIDATE_XML, new ValidateAction(validateAction));
}
private static void registerMetaData() {
final MetaDataRegistrar registrar = MetaDataRegistrar.getInstance();
registrar.registerMetaData(
new AndFilter(
new NamespaceFilter(ProjectLoader.RNG_NAMESPACE),
new ClassFilter(XmlDocument.class)
),
RngNsDescriptor.class);
registrar.registerMetaData(
new ClassFilter(RncDocument.class),
RngNsDescriptor.class);
registrar.registerMetaData(new ElementFilter() {
public boolean isAcceptable(Object element, PsiElement context) {
if (element instanceof XmlTag) {
final XmlTag tag = (XmlTag)element;
final DomElement domElement = DomManager.getDomManager(tag.getProject()).getDomElement(tag);
return domElement instanceof RngDefine;
}
return false;
}
public boolean isClassAcceptable(Class hintClass) {
return XmlTag.class.isAssignableFrom(hintClass);
}
}, RngDefineMetaData.class);
}
public void disposeComponent() {
}
public Class[] getInspectionClasses() {
return new Class[]{
RngDomInspection.class,
UnusedDefineInspection.class
};
}
public class ResourceProvider implements StandardResourceProvider {
public void registerResources(ResourceRegistrar registrar) {
registrar.addStdResource(ProjectLoader.RNG_NAMESPACE, "resources/relaxng.rng", getClass());
registrar.addIgnoredResource("http://relaxng.org/ns/compatibility/annotations/1.0");
}
}
}
@@ -0,0 +1,42 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG;
import org.intellij.plugins.relaxNG.model.resolve.RelaxSymbolIndex;
import com.intellij.navigation.ChooseByNameContributor;
import com.intellij.navigation.NavigationItem;
import com.intellij.openapi.project.Project;
import java.util.Collection;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 24.10.2007
*/
public class GotoSymbolContributor implements ChooseByNameContributor {
public NavigationItem[] getItemsByName(String name, String pattern, Project project, boolean includeNonProjectItems) {
return RelaxSymbolIndex.getSymbolsByName(name, project, includeNonProjectItems);
}
public String[] getNames(Project project, boolean includeNonProjectItems) {
final Collection<String> names = RelaxSymbolIndex.getSymbolNames(project);
return names.toArray(new String[names.size()]);
}
}
@@ -0,0 +1,152 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.patterns.StringPattern;
import com.intellij.patterns.XmlNamedElementPattern;
import com.intellij.psi.AbstractElementManipulator;
import com.intellij.psi.PsiManager;
import com.intellij.psi.filters.position.PatternFilter;
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.xml.DomFileDescription;
import com.intellij.util.xml.DomManager;
import com.intellij.util.xml.highlighting.DomElementsAnnotator;
import com.intellij.xml.util.XmlUtil;
import org.intellij.plugins.relaxNG.compact.RncTokenTypes;
import org.intellij.plugins.relaxNG.compact.psi.RncFileReference;
import org.intellij.plugins.relaxNG.compact.psi.util.RenameUtil;
import org.intellij.plugins.relaxNG.model.annotation.ModelAnnotator;
import org.intellij.plugins.relaxNG.references.PrefixReferenceProvider;
import org.intellij.plugins.relaxNG.xml.dom.*;
import org.intellij.plugins.relaxNG.xml.dom.impl.RngDefineImpl;
import org.intellij.plugins.relaxNG.xml.dom.impl.RngGrammarImpl;
import org.intellij.plugins.relaxNG.xml.dom.impl.RngIncludeImpl;
import org.intellij.plugins.relaxNG.xml.dom.impl.RngRefImpl;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import static com.intellij.patterns.StandardPatterns.string;
import static com.intellij.patterns.XmlPatterns.*;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 16.07.2007
*/
public class ProjectLoader implements ProjectComponent {
public static final String RNG_NAMESPACE = "http://relaxng.org/ns/structure/1.0";
private static final XmlNamedElementPattern RNG_TAG_PATTERN = xmlTag().withNamespace(string().equalTo(RNG_NAMESPACE));
private static final XmlNamedElementPattern.XmlAttributePattern NAME_ATTR_PATTERN = xmlAttribute("name");
private static final StringPattern ELEMENT_OR_ATTRIBUTE_PATTERN = string().oneOf("element", "attribute");
private static final XmlNamedElementPattern.XmlAttributePattern NAME_PATTERN = NAME_ATTR_PATTERN.withParent(
RNG_TAG_PATTERN.withLocalName(ELEMENT_OR_ATTRIBUTE_PATTERN));
private final Project myProject;
public ProjectLoader(Project project) {
myProject = project;
}
@NonNls
@NotNull
public String getComponentName() {
return "RELAX-NG";
}
public void initComponent() {
registerFileDescriptions();
registerReferences();
}
private void registerReferences() {
final ReferenceProvidersRegistry registry = ReferenceProvidersRegistry.getInstance(myProject);
XmlUtil.registerXmlAttributeValueReferenceProvider(registry, new String[]{
"name"
}, new PatternFilter(xmlAttributeValue().withParent(NAME_PATTERN)), true, new PrefixReferenceProvider());
// final XmlAttributeValuePattern id = xmlAttributeValue().withParent(xmlAttribute()).with(IdRefProvider.HAS_ID_REF_TYPE);
// final XmlAttributeValuePattern idref = xmlAttributeValue().withParent(xmlAttribute()).with(IdRefProvider.HAS_ID_TYPE);
// registry.registerXmlAttributeValueReferenceProvider(null, new PatternFilter(or(id, idref)), false, new IdRefProvider());
}
@SuppressWarnings({ "deprecation" })
private void registerFileDescriptions() {
final DomManager mgr = DomManager.getDomManager(myProject);
mgr.registerFileDescription(new MyFileDescription<RngGrammar>(RngGrammar.class, "grammar"));
mgr.registerFileDescription(new MyFileDescription<RngElement>(RngElement.class, "element"));
mgr.registerFileDescription(new MyFileDescription<RngChoice>(RngChoice.class, "choice"));
mgr.registerFileDescription(new MyFileDescription<RngGroup>(RngGroup.class, "group"));
mgr.registerFileDescription(new MyFileDescription<RngInterleave>(RngInterleave.class, "interleave"));
}
public void disposeComponent() {
}
public void projectOpened() {
}
public void projectClosed() {
}
private static class MyFileDescription<T> extends DomFileDescription<T> {
public MyFileDescription(Class<T> elementClass, String rootTagName) {
super(elementClass, rootTagName);
registerNamespacePolicy("RELAX-NG", RNG_NAMESPACE);
registerImplementation(RngDefine.class, RngDefineImpl.class);
registerImplementation(RngGrammar.class, RngGrammarImpl.class);
registerImplementation(RngInclude.class, RngIncludeImpl.class);
registerImplementation(RngRef.class, RngRefImpl.class);
}
public boolean isAutomaticHighlightingEnabled() {
return true;
}
public DomElementsAnnotator createAnnotator() {
return new ModelAnnotator();
}
}
public static class RncFileReferenceManipulator extends AbstractElementManipulator<RncFileReference> {
public RncFileReference handleContentChange(RncFileReference element, TextRange range, String newContent) throws IncorrectOperationException {
final ASTNode node = element.getNode();
assert node != null;
final ASTNode literal = node.findChildByType(RncTokenTypes.LITERAL);
if (literal != null) {
assert range.equals(element.getReferenceRange());
final PsiManager manager = PsiManager.getInstance(element.getProject());
final ASTNode newChild = RenameUtil.createLiteralNode(manager, newContent);
literal.getTreeParent().replaceChild(literal, newChild);
}
return element;
}
@Override
public TextRange getRangeInElement(RncFileReference element) {
return element.getReferenceRange();
}
}
}
@@ -0,0 +1,148 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG;
import org.intellij.plugins.relaxNG.model.descriptors.CompositeDescriptor;
import org.intellij.plugins.relaxNG.model.descriptors.RngElementDescriptor;
import org.intellij.plugins.relaxNG.model.descriptors.RngXmlAttributeDescriptor;
import com.intellij.lang.documentation.DocumentationProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlTag;
import com.intellij.xml.XmlAttributeDescriptor;
import com.intellij.xml.XmlElementDescriptor;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import org.kohsuke.rngom.digested.DElementPattern;
import java.util.Collection;
import java.util.List;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 19.11.2007
*/
public class RngDocumentationProvider implements DocumentationProvider {
@NonNls
private static final String COMPATIBILITY_ANNOTATIONS_1_0 = "http://relaxng.org/ns/compatibility/annotations/1.0";
@Nullable
public String generateDoc(PsiElement element, PsiElement originalElement) {
final XmlElement c = PsiTreeUtil.getParentOfType(originalElement, XmlTag.class, XmlAttribute.class);
if (c instanceof XmlTag) {
final XmlTag xmlElement = (XmlTag)c;
final XmlElementDescriptor descriptor = xmlElement.getDescriptor();
if (descriptor instanceof CompositeDescriptor) {
final StringBuilder sb = new StringBuilder();
final CompositeDescriptor d = (CompositeDescriptor)descriptor;
final DElementPattern[] patterns = d.getElementPatterns();
for (DElementPattern pattern : patterns) {
final PsiElement psiElement = d.getDeclaration(pattern.getLocation());
if (psiElement instanceof XmlTag) {
if (sb.length() > 0) {
sb.append("<hr>");
}
sb.append(getDocumentationFromTag((XmlTag)psiElement, xmlElement.getLocalName(), "Element"));
}
}
return makeDocumentation(sb);
} else if (descriptor instanceof RngElementDescriptor) {
final RngElementDescriptor d = (RngElementDescriptor)descriptor;
final PsiElement declaration = d.getDeclaration();
if (declaration instanceof XmlTag) {
return makeDocumentation(getDocumentationFromTag((XmlTag)declaration, xmlElement.getLocalName(), "Element"));
}
}
} else if (c instanceof XmlAttribute) {
final XmlAttribute attribute = (XmlAttribute)c;
final XmlAttributeDescriptor descriptor = attribute.getDescriptor();
if (descriptor instanceof RngXmlAttributeDescriptor) {
final RngXmlAttributeDescriptor d = (RngXmlAttributeDescriptor)descriptor;
final StringBuilder sb = new StringBuilder();
final Collection<PsiElement> declaration = d.getDeclarations();
for (PsiElement psiElement : declaration) {
if (psiElement instanceof XmlTag) {
if (sb.length() > 0) {
sb.append("<hr>");
}
sb.append(getDocumentationFromTag((XmlTag)element, d.getName(), "Attribute"));
}
}
}
} else if (element instanceof XmlTag) {
return makeDocumentation(getDocumentationFromTag((XmlTag)element, ((XmlTag)element).getLocalName(), "Element"));
}
return null;
}
private static String makeDocumentation(StringBuilder sb) {
if (!sb.toString().startsWith("<html>")) {
sb.insert(0, "<html>");
sb.append("</html>");
}
return sb.toString().replaceAll("\n", "<br>");
}
private static StringBuilder getDocumentationFromTag(XmlTag tag, String localName, String kind) {
if (tag.getNamespace().equals(ProjectLoader.RNG_NAMESPACE)) {
final StringBuilder sb = new StringBuilder();
sb.append(kind).append(": <b>").append(localName).append("</b><br>");
final XmlTag[] docTags = tag.findSubTags("documentation", COMPATIBILITY_ANNOTATIONS_1_0);
for (XmlTag docTag : docTags) {
sb.append(docTag.getValue().getTrimmedText());
sb.append("\n");
}
final XmlTag nextTag = PsiTreeUtil.getNextSiblingOfType(tag, XmlTag.class);
if (nextTag != null) {
if ("documentation".equals(nextTag.getLocalName()) && COMPATIBILITY_ANNOTATIONS_1_0.equals(nextTag.getNamespace())) {
sb.append(nextTag.getValue().getTrimmedText());
}
}
return sb;
}
return null;
}
@Nullable
public PsiElement getDocumentationElementForLink(PsiManager psiManager, String link, PsiElement context) {
return null;
}
@Nullable
public PsiElement getDocumentationElementForLookupItem(PsiManager psiManager, Object object, PsiElement element) {
return null;
}
@Nullable
public String getQuickNavigateInfo(PsiElement element) {
return null;
}
public List<String> getUrlFor(PsiElement element, PsiElement originalElement) {
return null;
}
public int hashCode() {
return 0; // CompositeDocumentationProvider uses a HashSet that doesn't preserve order. We want to be the first one.
}
}
@@ -0,0 +1,135 @@
/*
* Copyright 2006 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG;
import com.intellij.ide.BrowserUtil;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.openapi.diagnostic.ErrorReportSubmitter;
import com.intellij.openapi.diagnostic.IdeaLoggingEvent;
import com.intellij.openapi.diagnostic.SubmittedReportInfo;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import java.awt.*;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class SimpleErrorReportSubmitter extends ErrorReportSubmitter {
public String getReportActionText() {
return "Error Report Information";
}
public SubmittedReportInfo submit(IdeaLoggingEvent[] events, Component parentComponent) {
final IdeaPluginDescriptor plugin = PluginManager.getPlugin(getPluginDescriptor().getPluginId());
assert plugin != null;
final String title = plugin.getName() + " - " + plugin.getVersion();
final String vendorEmail = plugin.getVendorEmail();
final String subject = title + " Exception";
final String mailto = "mailto:" + encode(vendorEmail) + "?Subject=" + encode(subject) /*+
"&body=" + encode("Stacktrace:\n" + events[0].getThrowableText())*/;
final String weblink = "http://www.intellij.net/forums/forum.jsp?forum=18";
final String website = plugin.getUrl();
final String font = new JLabel().getFont().getName();
String message = "<html><span style='font: " + font + "; font-size:smaller'>" +
"To report an exception, please post the exception stacktrace and a short description " +
"of how it can be reproduced to the IntelliJ " +
"<a href='" + weblink + "'>plugin web forum</a> or the corresponding newsgroup, " +
"and/or send an email containing that information to " +
"<a href='" + mailto + "'>" + vendorEmail + "</a>." +
(website != null ? "<br><br>Please also check the plugin's <a href='" + website + "'>website</a> for more information." : "") +
"</span></html>";
final JEditorPane pane = new JEditorPane("text/html", message);
pane.setEditable(false);
pane.setPreferredSize(new Dimension(410, website != null ? 110 : 80));
pane.addHyperlinkListener(new HyperlinkListener() {
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
BrowserUtil.launchBrowser(e.getURL().toExternalForm());
}
}
});
new MyMessageDialog(parentComponent, title, Messages.getErrorIcon(), pane).show();
return new SubmittedReportInfo(null, null, SubmittedReportInfo.SubmissionStatus.FAILED);
}
private String encode(String link) {
final String enc = System.getProperty("file.encoding");
try {
return URLEncoder.encode(link, enc).replaceAll("\\+", "%20");
} catch (UnsupportedEncodingException e) {
throw new Error(e);
}
}
private static class MyMessageDialog extends DialogWrapper {
protected JComponent myMessage;
protected Icon myIcon;
public MyMessageDialog(Component parent, String title, Icon icon, JComponent message) {
super(parent, false);
_init(title, message, icon);
}
private void _init(String title, JComponent message, Icon icon) {
setTitle(title);
myMessage = message;
myIcon = icon;
setButtonsAlignment(SwingUtilities.CENTER);
init();
myMessage.setBackground(getContentPane().getBackground());
}
protected Action[] createActions() {
return new Action[]{ getOKAction() };
}
protected JComponent createNorthPanel() {
JPanel panel = new JPanel(new BorderLayout(15, 0));
if (myIcon != null) {
JLabel iconLabel = new JLabel(myIcon);
Container container = new Container();
container.setLayout(new BorderLayout());
container.add(iconLabel, BorderLayout.NORTH);
panel.add(container, BorderLayout.WEST);
}
if (myMessage != null) {
panel.add(myMessage, BorderLayout.CENTER);
}
return panel;
}
@Nullable
protected JComponent createCenterPanel() {
return null;
}
}
}
@@ -0,0 +1,126 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact;
import org.intellij.plugins.relaxNG.compact.psi.*;
import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider;
import com.intellij.codeInsight.daemon.QuickFixProvider;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.lang.annotation.Annotation;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiPolyVariantReference;
import com.intellij.psi.PsiReference;
import org.jetbrains.annotations.NotNull;
import java.text.MessageFormat;
import java.util.List;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 10.08.2007
*/
public class ReferenceAnnotator extends RncElementVisitor implements Annotator {
private AnnotationHolder myHolder;
public synchronized void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder holder) {
myHolder = holder;
try {
psiElement.accept(this);
} finally {
myHolder = null;
}
}
@Override
public void visitInclude(RncInclude include) {
checkReferences(include.getReferences());
}
@Override
public void visitExternalRef(RncExternalRef ref) {
checkReferences(ref.getReferences());
}
@Override
public void visitRef(RncRef pattern) {
checkReferences(pattern.getReferences());
}
@Override
public void visitParentRef(RncParentRef pattern) {
checkReferences(pattern.getReferences());
}
@Override
public void visitName(RncName name) {
checkReferences(name.getReferences());
}
private void checkReferences(PsiReference[] references) {
for (PsiReference reference : references) {
if (!reference.isSoft()) {
if (reference.resolve() == null) {
if (reference instanceof PsiPolyVariantReference) {
final PsiPolyVariantReference pvr = (PsiPolyVariantReference)reference;
if (pvr.multiResolve(false).length == 0) {
addError(reference);
}
} else {
addError(reference);
}
}
}
}
}
private void addError(PsiReference reference) {
final TextRange rangeInElement = reference.getRangeInElement();
final TextRange range = TextRange.from(reference.getElement().getTextRange().getStartOffset()
+ rangeInElement.getStartOffset(), rangeInElement.getLength());
final Annotation annotation;
if (reference instanceof EmptyResolveMessageProvider) {
final String s = ((EmptyResolveMessageProvider)reference).getUnresolvedMessagePattern();
annotation = myHolder.createErrorAnnotation(range, s != null ?
MessageFormat.format(s, reference.getCanonicalText())
: "Cannot resolve symbol");
} else {
annotation = myHolder.createErrorAnnotation(range, "Cannot resolve symbol");
}
annotation.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
if (reference instanceof QuickFixProvider) {
final HighlightInfo info = new HighlightInfo(HighlightInfoType.WRONG_REF, annotation.getStartOffset(), annotation.getEndOffset(), "", null);
((QuickFixProvider)reference).registerQuickfix(info, reference);
final List<Pair<HighlightInfo.IntentionActionDescriptor,TextRange>> ranges = info.quickFixActionRanges;
if (ranges != null) {
for (Pair<HighlightInfo.IntentionActionDescriptor, TextRange> pair : ranges) {
annotation.registerFix(pair.first.getAction(), pair.second);
}
}
}
}
}
@@ -0,0 +1,137 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact;
import com.intellij.codeInsight.TailType;
import com.intellij.codeInsight.completion.CompletionContext;
import com.intellij.codeInsight.completion.CompletionData;
import com.intellij.codeInsight.completion.CompletionVariant;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementFactory;
import com.intellij.patterns.ElementPattern;
import com.intellij.patterns.PsiElementPattern;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.filters.AndFilter;
import com.intellij.psi.filters.ContextGetter;
import com.intellij.psi.filters.ElementFilter;
import com.intellij.psi.filters.position.PatternFilter;
import com.intellij.psi.impl.source.tree.LeafPsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.intellij.plugins.relaxNG.compact.psi.RncDecl;
import org.intellij.plugins.relaxNG.compact.psi.RncDefine;
import org.intellij.plugins.relaxNG.compact.psi.RncElement;
import org.intellij.plugins.relaxNG.compact.psi.RncGrammar;
import org.intellij.plugins.relaxNG.compact.psi.util.EscapeUtil;
import static com.intellij.patterns.PlatformPatterns.psiElement;
import static com.intellij.patterns.StandardPatterns.*;
public class RncCompletionData extends CompletionData {
public RncCompletionData() {
declareFinalScope(RncElement.class);
final CompletionVariant variant = new CompletionVariant(new AndFilter(
new ElementFilter() {
public boolean isAcceptable(Object element, PsiElement context) {
return true;
}
public boolean isClassAcceptable(Class hintClass) {
return PsiElement.class.isAssignableFrom(hintClass);
}
},
new PatternFilter(or(
psiElement().afterLeaf(psiElement(RncTokenTypes.KEYWORD_DEFAULT)),
not(
or(
psiElement().inside(psiElement(RncTokenTypes.LITERAL)),
psiElement().afterLeaf(psiElement().withElementType(RncTokenTypes.KEYWORDS))
)
)
))
));
variant.includeScopeClass(LeafPsiElement.class, true);
variant.addCompletion(new KeywordGetter());
registerVariant(variant);
}
private static class KeywordGetter implements ContextGetter {
private static final ElementPattern TOP_LEVEL =
not(psiElement().inside(psiElement(RncGrammar.class)
.inside(true, psiElement(RncGrammar.class))));
private static final PsiElementPattern DECL_PATTERN =
psiElement().inside(psiElement(RncDecl.class));
private static final PsiElementPattern DEFAULT_PATTERN =
DECL_PATTERN.afterLeaf(psiElement().withText("default"));
private static final ElementPattern DEFINE_PATTERN =
and(psiElement().withParent(RncDefine.class), psiElement().afterLeafSkipping(psiElement(PsiWhiteSpace.class), psiElement().withText("=")));
private static final String[] DECL_KEYWORDS = new String[]{ "default", "namespace", "datatypes" };
private static final String[] GRAMMAR_CONTENT_KEYWORDS = new String[]{ "include", "div", "start" };
private static final String[] PATTERN_KEYWORDS = new String[]{ "attribute", "element", "grammar",
"notAllowed", "text", "empty", "external", "parent", "list", "mixed" };
public Object[] get(PsiElement context, CompletionContext completionContext) {
return ContainerUtil.map2Array(doGetKeywords(context), LookupElement.class, new Function<String, LookupElement>() {
public LookupElement fun(String s) {
return LookupElementFactory.getInstance().createLookupElement(s).setTailType(TailType.SPACE).setBold();
}
});
}
private String[] doGetKeywords(PsiElement context) {
final PsiElement next = PsiTreeUtil.skipSiblingsForward(context, PsiWhiteSpace.class);
if (next != null && EscapeUtil.unescapeText(next).equals("=")) {
return new String[]{ "start" };
}
if (DEFAULT_PATTERN.accepts(context)) {
return new String[]{ "namespace" };
} else if (DECL_PATTERN.accepts(context)) {
return ArrayUtil.EMPTY_STRING_ARRAY;
} else if (context.getParent() instanceof RncDefine && context.getParent().getFirstChild() == context) {
if (DEFINE_PATTERN.accepts(context)) {
return ArrayUtil.EMPTY_STRING_ARRAY;
}
if (TOP_LEVEL.accepts(context)) {
if (!afterPattern(context)) {
return ArrayUtil.mergeArrays(DECL_KEYWORDS,
ArrayUtil.mergeArrays(GRAMMAR_CONTENT_KEYWORDS, PATTERN_KEYWORDS, String.class), String.class);
}
}
return GRAMMAR_CONTENT_KEYWORDS;
}
return PATTERN_KEYWORDS;
}
private boolean afterPattern(PsiElement context) {
// TODO: recognize all patterns
return PsiTreeUtil.getPrevSiblingOfType(context.getParent(), RncDefine.class) != null;
}
}
}
@@ -0,0 +1,56 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact;
import org.intellij.plugins.relaxNG.compact.psi.RncElement;
import com.intellij.lang.ASTNode;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.NotNullFunction;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
public class RncElementType extends IElementType {
public RncElementType(String name) {
super(name, RngCompactLanguage.INSTANCE);
}
}
class RncElementTypeEx<C extends RncElement> extends RncElementType implements NotNullFunction<ASTNode, C> {
private final Constructor<? extends C> myConstructor;
RncElementTypeEx(String name, Class<? extends C> clazz) {
super(name);
assert !clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers());
try {
myConstructor = clazz.getConstructor(ASTNode.class);
} catch (NoSuchMethodException e) {
throw new Error(e);
}
}
@NotNull
public final C fun(ASTNode node) {
try {
return myConstructor.newInstance(node);
} catch (Exception e) {
throw new Error(e);
}
}
}
@@ -0,0 +1,74 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact;
import org.intellij.plugins.relaxNG.compact.psi.*;
import org.intellij.plugins.relaxNG.compact.psi.impl.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.IFileElementType;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 01.08.2007
*/
public class RncElementTypes {
public static final IFileElementType FILE_ELEMENT_TYPE = new IFileElementType(RngCompactLanguage.INSTANCE);
public static final IElementType DOCUMENT = new RncElementTypeEx<RncDocument>("DOCUMENT", RncDocument.class);
public static final IElementType NS_DECL = new RncElementTypeEx<RncNsDecl>("NS_DECL", RncNsDeclImpl.class);
public static final IElementType DATATYPES_DECL = new RncElementTypeEx<RncDecl>("DATATYPES_DECL", RncDeclImpl.class);
public static final IElementType START = new RncElementType("START");
public static final IElementType DIV = new RncElementTypeEx<RncDiv>("DIV", RncDivImpl.class);
public static final IElementType INCLUDE = new RncElementTypeEx<RncInclude>("INCLUDE", RncIncludeImpl.class);
public static final IElementType NAME_CLASS = new RncElementType("NAME_CLASS");
public static final IElementType NAME_CLASS_CHOICE = new RncElementType("NAME_CLASS_CHOICE");
public static final IElementType EXCEPT_NAME_CLASS = new RncElementType("EXCEPT_NAME_CLASS");
public static final IElementType DEFINE = new RncElementTypeEx<RncDefine>("DEFINE", RncDefineImpl.class);
public static final IElementType PATTERN = new RncElementType("PATTERN");
public static final IElementType GROUP_PATTERN = new RncElementType("GROUP_PATTERN");
public static final IElementType GRAMMAR_PATTERN = new RncElementTypeEx<RncGrammar>("GRAMMAR_PATTERN", RncGrammarImpl.class);
public static final IElementType EMPTY_PATTERN = new RncElementType("EMPTY_PATTERN");
public static final IElementType TEXT_PATTERN = new RncElementType("TEXT_PATTERN");
public static final IElementType NOT_ALLOWED_PATTERN = new RncElementType("NOT_ALLOWED_PATTERN");
public static final IElementType EXTERNAL_REF = new RncElementTypeEx<RncExternalRef>("EXTERNAL_REF", RncExternalRefImpl.class);
public static final IElementType PARENT_REF = new RncElementTypeEx<RncParentRef>("PARENT_REF", RncParentRefImpl.class);
public static final IElementType REF_PATTERN = new RncElementTypeEx<RncRef>("REF_PATTERN", RncRefImpl.class);
public static final IElementType LIST_PATTERN = new RncElementType("LIST_PATTERN");
public static final IElementType MIXED_PATTERN = new RncElementType("MIXED_PATTERN");
public static final IElementType DATATYPE_PATTERN = new RncElementType("DATATYPE_PATTERN");
public static final IElementType PARAM = new RncElementType("PARAM");
public static final IElementType SEQUENCE = new RncElementType("SEQUENCE");
public static final IElementType INTERLEAVE = new RncElementType("INTERLEAVE");
public static final IElementType CHOICE = new RncElementType("CHOICE");
public static final IElementType OPTIONAL = new RncElementType("OPTIONAL");
public static final IElementType ZERO_OR_MORE = new RncElementType("ZERO_OR_MORE");
public static final IElementType ONE_OR_MORE = new RncElementType("ONE_OR_MORE");
public static final IElementType NAME = new RncElementTypeEx<RncName>("NAME", RncNameImpl.class);
public static final IElementType ANNOTATION = new RncElementTypeEx<RncAnnotation>("ANNOTATION", RncAnnotationImpl.class);
public static final IElementType ANNOTATION_ELEMENT = new RncElementTypeEx<RncAnnotation>("ANNOTATION_ELEMENT", RncAnnotationImpl.class);
public static final IElementType FORWARD_ANNOTATION = new RncElementTypeEx<RncAnnotation>("FORWARD_ANNOTATION", RncAnnotationImpl.class);
}
@@ -0,0 +1,83 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeConsumer;
import com.intellij.openapi.fileTypes.FileTypeFactory;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.util.IconLoader;
import com.intellij.util.PairConsumer;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 01.08.2007
*/
public class RncFileType extends LanguageFileType {
public static final String RNC_EXT = "rnc";
private static FileType INSTANCE;
private RncFileType() {
super(RngCompactLanguage.INSTANCE);
}
@NotNull
@NonNls
public String getName() {
return "RNG Compact";
}
@NotNull
public String getDescription() {
return "RELAX NG Compact Syntax";
}
@NotNull
@NonNls
public String getDefaultExtension() {
return "rnc";
}
@Nullable
public Icon getIcon() {
return IconLoader.findIcon("/fileTypes/text.png");
}
public static synchronized FileType getInstance() {
if (INSTANCE == null) {
INSTANCE = new RncFileType();
}
return INSTANCE;
}
public static class Factory extends FileTypeFactory {
public void createFileTypes(@NotNull FileTypeConsumer fileTypeConsumer) {
fileTypeConsumer.consume(getInstance(), RNC_EXT);
}
public void createFileTypes(@NotNull PairConsumer<FileType, String> consumer) {
consumer.consume(getInstance(), RNC_EXT);
}
}
}
@@ -0,0 +1,77 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact;
import org.intellij.plugins.relaxNG.compact.lexer.CompactSyntaxLexerAdapter;
import com.intellij.lexer.Lexer;
import com.intellij.openapi.editor.HighlighterColors;
import com.intellij.openapi.editor.SyntaxHighlighterColors;
import com.intellij.openapi.editor.colors.CodeInsightColors;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.fileTypes.SyntaxHighlighterBase;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 04.08.2007
*/
public class RncHighlighter extends SyntaxHighlighterBase {
@NotNull
public Lexer getHighlightingLexer() {
return new CompactSyntaxLexerAdapter();
}
private static final Map<IElementType, TextAttributesKey> ourMap1;
static {
ourMap1 = new HashMap<IElementType, TextAttributesKey>();
fillMap(ourMap1, RncTokenTypes.KEYWORDS, SyntaxHighlighterColors.KEYWORD);
fillMap(ourMap1, RncTokenTypes.OPERATORS, SyntaxHighlighterColors.OPERATION_SIGN);
fillMap(ourMap1, RncTokenTypes.STRINGS, SyntaxHighlighterColors.STRING);
ourMap1.put(RncTokenTypes.LBRACE, SyntaxHighlighterColors.BRACES);
ourMap1.put(RncTokenTypes.RBRACE, SyntaxHighlighterColors.BRACES);
ourMap1.put(RncTokenTypes.LBRACKET, SyntaxHighlighterColors.BRACKETS);
ourMap1.put(RncTokenTypes.RBRACKET, SyntaxHighlighterColors.BRACKETS);
ourMap1.put(RncTokenTypes.LPAREN, SyntaxHighlighterColors.PARENTHS);
ourMap1.put(RncTokenTypes.RPAREN, SyntaxHighlighterColors.PARENTHS);
ourMap1.put(RncTokenTypes.COMMA, SyntaxHighlighterColors.COMMA);
fillMap(ourMap1, RncTokenTypes.DOC_TOKENS, SyntaxHighlighterColors.DOC_COMMENT);
fillMap(ourMap1, RncTokenTypes.COMMENTS, SyntaxHighlighterColors.LINE_COMMENT);
fillMap(ourMap1, RncTokenTypes.IDENTIFIERS, CodeInsightColors.LOCAL_VARIABLE_ATTRIBUTES);
ourMap1.put(RncTokenTypes.ILLEGAL_CHAR, HighlighterColors.BAD_CHARACTER);
}
@NotNull
public TextAttributesKey[] getTokenHighlights(IElementType tokenType) {
return pack(ourMap1.get(tokenType));
}
}
@@ -0,0 +1,103 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact;
import org.intellij.plugins.relaxNG.compact.lexer.CompactSyntaxLexerAdapter;
import org.intellij.plugins.relaxNG.compact.parser.RncParser;
import org.intellij.plugins.relaxNG.compact.psi.RncElementVisitor;
import org.intellij.plugins.relaxNG.compact.psi.impl.RncElementImpl;
import org.intellij.plugins.relaxNG.compact.psi.impl.RncFileImpl;
import com.intellij.lang.ASTNode;
import com.intellij.lang.ParserDefinition;
import com.intellij.lang.PsiParser;
import com.intellij.lexer.Lexer;
import com.intellij.openapi.project.Project;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.TokenType;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.IFileElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.util.NotNullFunction;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 10.08.2007
*/
public class RncParserDefinition implements ParserDefinition {
@NotNull
public Lexer createLexer(Project project) {
return new CompactSyntaxLexerAdapter();
}
public PsiParser createParser(Project project) {
return new RncParser();
}
public IFileElementType getFileNodeType() {
return RncElementTypes.FILE_ELEMENT_TYPE;
}
@NotNull
public TokenSet getWhitespaceTokens() {
return TokenSet.create(TokenType.WHITE_SPACE);
}
@NotNull
public TokenSet getCommentTokens() {
return TokenSet.orSet(RncTokenTypes.COMMENTS, RncTokenTypes.DOC_TOKENS);
}
@NotNull
public TokenSet getStringLiteralElements() {
return TokenSet.create(RncTokenTypes.LITERAL);
}
@NotNull
@SuppressWarnings({ "unchecked" })
public PsiElement createElement(ASTNode node) {
final IElementType type = node.getElementType();
if (type instanceof NotNullFunction) {
return ((NotNullFunction<ASTNode, PsiElement>)type).fun(node);
}
return new MyRncElement(node);
}
public PsiFile createFile(FileViewProvider viewProvider) {
return new RncFileImpl(viewProvider);
}
public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) {
return SpaceRequirements.MAY;
}
private static class MyRncElement extends RncElementImpl {
public MyRncElement(ASTNode node) {
super(node);
}
public void accept(@NotNull RncElementVisitor visitor) {
visitor.visitElement(this);
}
}
}
@@ -0,0 +1,205 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull;
import gnu.trove.TIntObjectHashMap;
import gnu.trove.TObjectProcedure;
import org.kohsuke.rngom.parse.compact.CompactSyntaxConstants;
import java.lang.reflect.Field;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 04.08.2007
*/
public class RncTokenTypes {
private static final TIntObjectHashMap<IElementType> ourTokenTypes = new TIntObjectHashMap<IElementType>();
static {
assert RngCompactLanguage.INSTANCE != null;
try {
final Field[] fields = CompactSyntaxConstants.class.getFields();
for (Field field : fields) {
final String name = field.getName();
if (name.equals("DEFAULT")) break;
if (int.class.isAssignableFrom(field.getType())) {
Integer i = (Integer)field.get(null);
ourTokenTypes.put(i, new RncElementType(name));
}
}
final String[] tokens = CompactSyntaxConstants.tokenImage;
for (int i = 0; i < tokens.length; i++) {
String token = tokens[i];
if (token.matches("\"\\w*\"")) {
token = "KEYWORD_" + token.substring(1, token.length() - 1).toUpperCase();
} else if (token.matches("\".*\"")) {
token = token.substring(1, token.length() - 1);
}
if (ourTokenTypes.get(i) == null) {
ourTokenTypes.put(i, new RncElementType(token));
}
}
} catch (IllegalAccessException e) {
throw new Error(e);
}
}
@NotNull
public static IElementType get(int i) {
assert !ourTokenTypes.isEmpty();
final IElementType type = ourTokenTypes.get(i);
assert type != null : "Unknown token kind: " + i;
return type;
}
@NotNull
private static IElementType get(final String name) {
assert !ourTokenTypes.isEmpty();
final Ref<IElementType> ref = new Ref<IElementType>();
ourTokenTypes.forEachValue(new TObjectProcedure<IElementType>() {
public boolean execute(IElementType iElementType) {
if (iElementType.toString().equals(name)) {
ref.set(iElementType);
return false;
}
return true;
}
});
return ref.get();
}
private static final IElementType WS = get(CompactSyntaxConstants.WS);
public static final TokenSet WHITESPACE = TokenSet.create(WS);
public static final IElementType ILLEGAL_CHAR = get(CompactSyntaxConstants.ILLEGAL_CHAR);
public static final IElementType LBRACE = get("{");
public static final IElementType RBRACE = get("}");
public static final IElementType LBRACKET = get("[");
public static final IElementType RBRACKET = get("]");
public static final IElementType LPAREN = get("(");
public static final IElementType RPAREN = get(")");
public static final IElementType GTGT = get(CompactSyntaxConstants.FANNOTATE);
public static final TokenSet BRACES = TokenSet.create(LBRACE, RBRACE);
public static final IElementType EQ = get("=");
public static final IElementType PLUS = get("+");
public static final IElementType MINUS = get("-");
public static final IElementType STAR = get("*");
public static final IElementType AND = get("&");
public static final IElementType PIPE = get("|");
public static final IElementType QUEST = get("?");
public static final IElementType PREFIXED_NAME = get(CompactSyntaxConstants.PREFIXED_NAME);
public static final IElementType PREFIXED_STAR = get(CompactSyntaxConstants.PREFIX_STAR);
public static final IElementType CHOICE_EQ = get("|=");
public static final IElementType INTERLEAVE_EQ = get("&=");
public static final IElementType COMMA = get(",");
public static final TokenSet BINARY_OPS = TokenSet.create(
COMMA, PIPE, AND
);
public static final TokenSet QUANTIFIER_OPS = TokenSet.create(
PLUS, STAR, QUEST
);
public static final IElementType DOC = get(CompactSyntaxConstants.DOCUMENTATION);
public static final TokenSet DOC_TOKENS = TokenSet.create(
DOC,
get(CompactSyntaxConstants.DOCUMENTATION_AFTER_SINGLE_LINE_COMMENT),
get(CompactSyntaxConstants.DOCUMENTATION_CONTINUE)
);
public static final IElementType COMMENT = get(CompactSyntaxConstants.SINGLE_LINE_COMMENT);
public static final TokenSet COMMENTS = TokenSet.create(
COMMENT,
get(CompactSyntaxConstants.SINGLE_LINE_COMMENT_CONTINUE)
);
public static final IElementType ESCAPED_IDENTIFIER = get(CompactSyntaxConstants.ESCAPED_IDENTIFIER);
public static final TokenSet IDENTIFIERS = TokenSet.create(
get(CompactSyntaxConstants.IDENTIFIER),
ESCAPED_IDENTIFIER
);
public static final TokenSet OPERATORS = TokenSet.orSet(TokenSet.create(
CHOICE_EQ, INTERLEAVE_EQ), BINARY_OPS, QUANTIFIER_OPS);
public static final IElementType LITERAL = get(CompactSyntaxConstants.LITERAL);
public static final TokenSet STRINGS = TokenSet.create(LITERAL);
static final TokenSet READABLE_TEXT = TokenSet.orSet(
DOC_TOKENS, COMMENTS,
TokenSet.create(LITERAL));
public static final IElementType KEYWORD_ElEMENT = get("KEYWORD_ELEMENT");
public static final IElementType KEYWORD_ATTRIBUTE = get("KEYWORD_ATTRIBUTE");
public static final IElementType KEYWORD_NAMESPACE = get("KEYWORD_NAMESPACE");
public static final IElementType KEYWORD_LIST = get("KEYWORD_LIST");
public static final IElementType KEYWORD_MIXED = get("KEYWORD_MIXED");
public static final IElementType KEYWORD_EMPTY = get("KEYWORD_EMPTY");
public static final IElementType KEYWORD_GRAMMAR = get("KEYWORD_GRAMMAR");
public static final IElementType KEYWORD_TEXT = get("KEYWORD_TEXT");
public static final IElementType KEYWORD_PARENT = get("KEYWORD_PARENT");
public static final IElementType KEYWORD_EXTERNAL = get("KEYWORD_LIST");
public static final IElementType KEYWORD_NOT_ALLOWED = get("KEYWORD_NOTALLOWED");
public static final IElementType KEYWORD_START = get("KEYWORD_START");
public static final IElementType KEYWORD_INCLUDE = get("KEYWORD_INCLUDE");
public static final IElementType KEYWORD_DEFAULT = get("KEYWORD_DEFAULT");
public static final IElementType KEYWORD_INHERIT = get("KEYWORD_INHERIT");
public static final IElementType KEYWORD_STRING = get("KEYWORD_STRING");
public static final IElementType KEYWORD_TOKEN = get("KEYWORD_TOKEN");
public static final IElementType KEYWORD_DATATYPES = get("KEYWORD_DATATYPES");
public static final IElementType KEYWORD_DIV = get("KEYWORD_DIV");
public static final TokenSet KEYWORDS = TokenSet.create(
KEYWORD_ATTRIBUTE,
KEYWORD_DATATYPES,
KEYWORD_DEFAULT,
KEYWORD_DIV,
KEYWORD_ElEMENT,
KEYWORD_EMPTY,
KEYWORD_EXTERNAL,
KEYWORD_GRAMMAR,
KEYWORD_INCLUDE,
KEYWORD_INHERIT,
KEYWORD_LIST,
KEYWORD_MIXED,
KEYWORD_NAMESPACE,
KEYWORD_NOT_ALLOWED,
KEYWORD_PARENT,
KEYWORD_START,
KEYWORD_STRING,
KEYWORD_TEXT,
KEYWORD_TOKEN
);
public static final TokenSet IDENTIFIER_OR_KEYWORD = TokenSet.orSet(KEYWORDS, IDENTIFIERS);
}
@@ -0,0 +1,164 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact;
import org.intellij.plugins.relaxNG.compact.psi.RncDefine;
import org.intellij.plugins.relaxNG.compact.psi.RncElement;
import org.intellij.plugins.relaxNG.compact.psi.util.EscapeUtil;
import org.intellij.plugins.relaxNG.compact.psi.util.RenameUtil;
import com.intellij.lang.BracePair;
import com.intellij.lang.Commenter;
import com.intellij.lang.Language;
import com.intellij.lang.PairedBraceMatcher;
import com.intellij.lang.documentation.DocumentationProvider;
import com.intellij.lang.refactoring.NamesValidator;
import com.intellij.openapi.fileTypes.SingleLazyInstanceSyntaxHighlighterFactory;
import com.intellij.openapi.fileTypes.SyntaxHighlighter;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 01.08.2007
*/
public class RngCompactLanguage extends Language {
public static final String ID = "RELAX-NG";
public static final RngCompactLanguage INSTANCE = new RngCompactLanguage();
private RngCompactLanguage() {
super(ID);
}
public static class MyCommenter implements Commenter {
@Nullable
public String getLineCommentPrefix() {
return "#";
}
@Nullable
public String getBlockCommentPrefix() {
return null;
}
@Nullable
public String getBlockCommentSuffix() {
return null;
}
public String getCommentedBlockCommentPrefix() {
return null;
}
public String getCommentedBlockCommentSuffix() {
return null;
}
}
public static class MyPairedBraceMatcher implements PairedBraceMatcher {
private BracePair[] myBracePairs;
public BracePair[] getPairs() {
if (myBracePairs == null) {
myBracePairs = new BracePair[]{
new BracePair(RncTokenTypes.LBRACE, RncTokenTypes.RBRACE, true),
new BracePair(RncTokenTypes.LPAREN, RncTokenTypes.RPAREN, false),
new BracePair(RncTokenTypes.LBRACKET, RncTokenTypes.RBRACKET, false),
};
}
return myBracePairs;
}
public boolean isPairedBracesAllowedBeforeType(@NotNull IElementType lbraceType, @Nullable IElementType contextType) {
return false;
}
public int getCodeConstructStart(PsiFile file, int openingBraceOffset) {
// TODO
return openingBraceOffset;
}
}
public static class MyNamesValidator implements NamesValidator {
public boolean isKeyword(String name, Project project) {
return RenameUtil.isKeyword(PsiManager.getInstance(project), name);
}
public boolean isIdentifier(String name, Project project) {
return RenameUtil.isIdentifier(PsiManager.getInstance(project), name);
}
}
public static class MyDocumentationProvider implements DocumentationProvider {
@Nullable
public String getQuickNavigateInfo(PsiElement element) {
return null;
}
public List<String> getUrlFor(PsiElement element, PsiElement originalElement) {
return null;
}
@Nullable
public String generateDoc(PsiElement element, PsiElement originalElement) {
if (element instanceof RncElement) {
PsiElement comment = element.getPrevSibling();
while (comment instanceof PsiWhiteSpace) {
comment = comment.getPrevSibling();
}
if (comment instanceof PsiComment) {
final StringBuilder sb = new StringBuilder();
do {
sb.insert(0, EscapeUtil.unescapeText(comment).replaceAll("\n?##?", "") + "<br>");
comment = comment.getPrevSibling();
} while (comment instanceof PsiComment);
if (element instanceof RncDefine) {
sb.insert(0, "Define: <b>" + ((RncDefine)element).getName() + "</b><br>");
}
return sb.toString();
}
}
return null;
}
@Nullable
public PsiElement getDocumentationElementForLookupItem(PsiManager psiManager, Object object, PsiElement element) {
return null;
}
@Nullable
public PsiElement getDocumentationElementForLink(PsiManager psiManager, String link, PsiElement context) {
return null;
}
}
public static class MySyntaxHighlighterFactory extends SingleLazyInstanceSyntaxHighlighterFactory {
@NotNull
protected SyntaxHighlighter createHighlighter() {
return new RncHighlighter();
}
}
}
@@ -0,0 +1,158 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.folding;
import org.intellij.plugins.relaxNG.compact.RncElementTypes;
import org.intellij.plugins.relaxNG.compact.RncTokenTypes;
import org.intellij.plugins.relaxNG.compact.psi.RncAnnotation;
import org.intellij.plugins.relaxNG.compact.psi.RncName;
import org.intellij.plugins.relaxNG.compact.psi.util.EscapeUtil;
import com.intellij.codeInsight.folding.CodeFoldingSettings;
import com.intellij.lang.ASTNode;
import com.intellij.lang.folding.FoldingBuilder;
import com.intellij.lang.folding.FoldingDescriptor;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 10.08.2007
*/
public class RncFoldingBuilder implements FoldingBuilder {
@NotNull
public FoldingDescriptor[] buildFoldRegions(@NotNull ASTNode node, @NotNull Document document) {
final ArrayList<FoldingDescriptor> regions = new ArrayList<FoldingDescriptor>();
process(node, document, regions);
return regions.size() > 0
? regions.toArray(new FoldingDescriptor[regions.size()])
: FoldingDescriptor.EMPTY;
}
public String getPlaceholderText(@NotNull ASTNode node) {
final IElementType type = node.getElementType();
if (type == RncTokenTypes.LBRACE) {
return "{ ... }";
} else if (isCommentLike(type)) {
return "# ...";
} else if (isAnnotation(type)) {
final RncName element = ((RncAnnotation)node.getPsi()).getNameElement();
if (element != null) {
final ASTNode n = element.getNode();
assert n != null;
return EscapeUtil.unescapeText(n) + " [ ... ]";
}
return "[ ... ]";
} else {
return "...";
}
}
private static boolean isAnnotation(IElementType type) {
return RncElementTypes.ANNOTATION == type || RncElementTypes.ANNOTATION_ELEMENT == type || RncElementTypes.FORWARD_ANNOTATION == type;
}
private static boolean isCommentLike(IElementType type) {
return RncTokenTypes.COMMENTS.contains(type) || RncTokenTypes.DOC_TOKENS.contains(type);
}
public boolean isCollapsedByDefault(@NotNull ASTNode node) {
return isCommentLike(node.getElementType()) && CodeFoldingSettings.getInstance().COLLAPSE_DOC_COMMENTS;
}
private static void process(@Nullable ASTNode node, Document document, ArrayList<FoldingDescriptor> regions) {
if (node == null) {
return;
}
final ASTNode[] braces = node.getChildren(RncTokenTypes.BRACES);
if (braces.length == 2) {
final ASTNode lbrace = braces[0];
final ASTNode rbrace = braces[1];
if (shouldFold(lbrace, rbrace, document)) {
final TextRange range = new TextRange(lbrace.getStartOffset(), rbrace.getTextRange().getEndOffset());
regions.add(new FoldingDescriptor(lbrace, range));
}
} else if (isAnnotation(node.getElementType())) {
if (isOnDifferentLine(node.getFirstChildNode(), node.getLastChildNode(), document)) {
regions.add(new FoldingDescriptor(node, node.getTextRange()));
}
}
node = node.getFirstChildNode();
while (node != null) {
node = checkNodeAndSiblings(node, RncTokenTypes.DOC_TOKENS, regions, document);
node = checkNodeAndSiblings(node, RncTokenTypes.COMMENTS, regions, document);
process(node, document, regions);
if (node != null) {
node = node.getTreeNext();
}
}
}
@Nullable
private static ASTNode checkNodeAndSiblings(@Nullable ASTNode node, TokenSet tokens, ArrayList<FoldingDescriptor> regions, Document document) {
if (node != null && tokens.contains(node.getElementType())) {
final ASTNode start = node;
ASTNode end = start;
node = node.getTreeNext();
if (node != null) {
do {
end = node;
node = node.getTreeNext();
} while (node != null && tokens.contains(node.getElementType()));
}
if (end != start) {
while (end.getPsi() instanceof PsiWhiteSpace) {
end = end.getTreePrev();
}
if (isOnDifferentLine(start, end, document)) {
regions.add(new FoldingDescriptor(start, new TextRange(start.getStartOffset(), end.getTextRange().getEndOffset())));
}
}
}
return node;
}
private static boolean shouldFold(ASTNode first, ASTNode second, Document document) {
if (first.getElementType() != RncTokenTypes.LBRACE) {
return false;
} else if (second.getElementType() != RncTokenTypes.RBRACE) {
return false;
} else {
return isOnDifferentLine(first, second, document);
}
}
private static boolean isOnDifferentLine(ASTNode first, ASTNode second, Document document) {
return document.getLineNumber(first.getStartOffset()) != document.getLineNumber(second.getStartOffset());
}
}
@@ -0,0 +1,127 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.formatting;
import org.intellij.plugins.relaxNG.compact.RncElementTypes;
import org.intellij.plugins.relaxNG.compact.RncTokenTypes;
import org.intellij.plugins.relaxNG.compact.psi.RncDecl;
import org.intellij.plugins.relaxNG.compact.psi.RncDefine;
import org.intellij.plugins.relaxNG.compact.psi.RncFile;
import org.intellij.plugins.relaxNG.compact.psi.RncGrammar;
import org.intellij.plugins.relaxNG.compact.psi.impl.RncDocument;
import com.intellij.formatting.*;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
class RncBlock implements Block {
private final ASTNode myNode;
public RncBlock(ASTNode element) {
myNode = element;
}
@NotNull
public TextRange getTextRange() {
return myNode.getTextRange();
}
@NotNull
public List<Block> getSubBlocks() {
final List<Block> list = new ArrayList<Block>();
ASTNode node = myNode.getFirstChildNode();
while (node != null) {
if (!RncTokenTypes.WHITESPACE.contains(node.getElementType()) && node.getTextLength() > 0) {
list.add(new RncBlock(node));
}
node = node.getTreeNext();
}
return list;
}
@Nullable
public Wrap getWrap() {
// TODO
return null;
}
@Nullable
public Indent getIndent() {
if (isTopLevel()) {
return Indent.getAbsoluteNoneIndent();
} else if (myNode.getTreeParent().getPsi() instanceof RncGrammar && !RncTokenTypes.BRACES.contains(myNode.getElementType())) {
// TODO: fix block psi
return Indent.getNormalIndent();
}
return null;
}
private boolean isTopLevel() {
final PsiElement parent = myNode.getTreeParent().getPsi();
return parent instanceof RncDocument ||
parent instanceof RncFile ||
parent instanceof RncGrammar && parent.getParent() instanceof RncDocument;
}
@Nullable
public Alignment getAlignment() {
// TODO
return null;
}
@Nullable
public Spacing getSpacing(Block child1, Block child2) {
final ASTNode lnode = ((RncBlock)child1).myNode;
final PsiElement lpsi = lnode.getPsi();
final PsiElement rpsi = ((RncBlock)child2).myNode.getPsi();
if (lpsi instanceof RncDecl && rpsi instanceof RncDecl) {
return makeNewline();
}
if ((lpsi instanceof RncDecl || lpsi instanceof RncDefine ||
lnode.getElementType() == RncElementTypes.START) &&
(rpsi instanceof RncDefine || rpsi instanceof RncGrammar)) {
return makeNewline();
}
return null;
}
private static Spacing makeNewline() {
return Spacing.createSpacing(0, Integer.MAX_VALUE, 1, true, 100);
}
@NotNull
public ChildAttributes getChildAttributes(int newChildIndex) {
return new ChildAttributes(null, null);
}
public boolean isIncomplete() {
// TODO
return false;
}
public boolean isLeaf() {
// TODO
return false;
}
}
@@ -0,0 +1,39 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.formatting;
import com.intellij.formatting.FormattingModel;
import com.intellij.formatting.FormattingModelBuilder;
import com.intellij.formatting.FormattingModelProvider;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import org.jetbrains.annotations.NotNull;
public class RncFormattingModelBuilder implements FormattingModelBuilder {
@NotNull
public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) {
return FormattingModelProvider.createFormattingModelForPsiFile(element.getContainingFile(), new RncBlock(element.getNode()), settings);
}
public TextRange getRangeAffectingIndent(PsiFile file, int offset, ASTNode elementAtOffset) {
// TODO
return null;
}
}
@@ -0,0 +1,258 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.lexer;
import org.intellij.plugins.relaxNG.compact.RncTokenTypes;
import com.intellij.lexer.LexerBase;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.psi.TokenType;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.text.CharArrayCharSequence;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.Nullable;
import gnu.trove.TIntIntHashMap;
import org.kohsuke.rngom.parse.compact.CompactSyntaxConstants;
import org.kohsuke.rngom.parse.compact.CompactSyntaxTokenManager;
import org.kohsuke.rngom.parse.compact.Token;
import org.kohsuke.rngom.parse.compact.TokenMgrError;
import java.io.CharArrayReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Field;
import java.util.LinkedList;
/**
* An adapter to use the lexer ("TokenManager") generated from a javacc grammar.
*
* Not sure if it was easier to write this than hacking my own lexer...
*/
public class CompactSyntaxLexerAdapter extends LexerBase {
private static final Logger LOG = Logger.getInstance(CompactSyntaxLexerAdapter.class.getName());
private static final Field myStateField;
static {
try {
myStateField = CompactSyntaxTokenManager.class.getDeclaredField("curLexState");
myStateField.setAccessible(true);
} catch (NoSuchFieldException e) {
throw new Error(e);
}
}
private static final Token START = new Token();
private CompactSyntaxTokenManager myLexer;
private final LinkedList<Token> myTokenQueue = new LinkedList<Token>();
private Token myCurrentToken;
private int myCurrentOffset;
private int myCurrentEnd;
private IElementType myCurrentTokenType;
private CharSequence myBuffer;
private int myEndOffset;
private TIntIntHashMap myLengthMap;
public void advance() {
try {
myCurrentToken = nextToken();
myCurrentOffset = myCurrentEnd;
if (myCurrentToken != null) {
myCurrentEnd = myCurrentOffset + myCurrentToken.image.length();
for (int i = myCurrentOffset; i < myCurrentEnd; i++) {
myCurrentEnd += myLengthMap.get(i);
}
if (myCurrentToken.kind == CompactSyntaxConstants.EOF) {
assert myCurrentOffset == myEndOffset : "actual: " + myCurrentOffset + ", expected: " + myEndOffset;
myCurrentToken = null;
}
}
// if (myCurrentToken != null) {
// System.out.println("token = <" + RncTokenTypes.get(myCurrentToken.kind).toString() + "> [" + myCurrentToken.image + "]");
// }
} catch (TokenMgrError e) {
LOG.error(e);
myCurrentToken = null;
}
if (myCurrentToken == null) {
myCurrentTokenType = null;
} else {
myCurrentTokenType = RncTokenTypes.get(myCurrentToken.kind);
// collapse whitespace tokens into TokenType.WHITE_SPACE [IDEA-12106]
if (RncTokenTypes.WHITESPACE.contains(myCurrentTokenType)) {
myCurrentTokenType = TokenType.WHITE_SPACE;
}
}
}
private Token nextToken() {
if (myTokenQueue.size() > 0) {
return myTokenQueue.removeFirst();
}
final Token t = myLexer.getNextToken();
if (t.specialToken != null) {
myTokenQueue.addFirst(t);
for (Token s = t.specialToken; s != null; s = s.specialToken) {
myTokenQueue.addFirst(s);
}
return myTokenQueue.removeFirst();
} else {
return t;
}
}
@Deprecated
public char[] getBuffer() {
return CharArrayUtil.fromSequence(myBuffer);
}
@Override
public CharSequence getBufferSequence() {
return myBuffer;
}
public int getBufferEnd() {
return myEndOffset;
}
public int getState() {
try {
return (Integer)myStateField.get(myLexer);
} catch (Exception e) {
return -1;
}
}
public int getTokenEnd() {
return myCurrentEnd;
}
public int getTokenStart() {
return myCurrentToken == null ? 0 : myCurrentOffset;
}
@Nullable
public IElementType getTokenType() {
if (myCurrentToken == null) {
return null;
} else {
return myCurrentTokenType;
}
}
@Deprecated
public void start(char[] buffer, int startOffset, int endOffset, int initialState) {
myBuffer = new CharArrayCharSequence(buffer, startOffset, endOffset);
final CharArrayReader reader = new CharArrayReader(buffer, startOffset, endOffset - startOffset);
init(startOffset, endOffset, reader, initialState);
}
public void start(CharSequence buffer, int startOffset, int endOffset, int initialState) {
myBuffer = buffer;
final Reader reader = new CharSequenceReader(buffer, startOffset, endOffset);
init(startOffset, endOffset, reader, initialState);
}
private void init(int startOffset, int endOffset, Reader reader, int initialState) {
myEndOffset = endOffset;
myLengthMap = new TIntIntHashMap();
final EscapePreprocessor preprocessor = new EscapePreprocessor(reader, startOffset, myLengthMap);
myLexer = new CompactSyntaxTokenManager(new SimpleCharStream(preprocessor, 1, 1), initialState);
myCurrentToken = START;
myCurrentOffset = startOffset;
myCurrentEnd = startOffset;
myTokenQueue.clear();
advance();
}
public static void main(String[] args) throws IOException {
final CompactSyntaxLexerAdapter lexer = new CompactSyntaxLexerAdapter();
lexer.start(new CharArrayCharSequence(FileUtil.adaptiveLoadText(new FileReader(args[0]))));
while (lexer.getTokenType() != null) {
System.out.println("token = " + lexer.getTokenType());
final int start = lexer.getTokenStart();
System.out.println("start = " + start);
final int end = lexer.getTokenEnd();
System.out.println("end = " + end);
final CharSequence t = lexer.getBufferSequence().subSequence(start, end);
System.out.println("t = " + t);
lexer.advance();
}
}
// adapted from com.intellij.util.text.CharSequenceReader with start- and endOffset support
static class CharSequenceReader extends Reader {
private final CharSequence myText;
private final int myEndOffset;
private int myCurPos;
public CharSequenceReader(final CharSequence text, int startOffset, int endOffset) {
myText = text;
myEndOffset = endOffset;
myCurPos = startOffset;
}
public void close() {
}
public int read(char[] cbuf, int off, int len) {
if ((off < 0) || (off > cbuf.length) || (len < 0) || ((off + len) > cbuf.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
if (myText instanceof CharArrayCharSequence) { // Optimization
final int readChars = ((CharArrayCharSequence)myText).readCharsTo(myCurPos, cbuf, off, len);
if (readChars < 0) return -1;
myCurPos += readChars;
return readChars;
}
int charsToCopy = Math.min(len, myEndOffset - myCurPos);
if (charsToCopy <= 0) return -1;
for (int n = 0; n < charsToCopy; n++) {
cbuf[n + off] = myText.charAt(n + myCurPos);
}
myCurPos += charsToCopy;
return charsToCopy;
}
public int read() {
if (myCurPos >= myEndOffset) return -1;
return myText.charAt(myCurPos++);
}
}
}
@@ -0,0 +1,140 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.lexer;
import gnu.trove.TIntArrayList;
import gnu.trove.TIntIntHashMap;
import org.kohsuke.rngom.util.Utf16;
import java.io.FilterReader;
import java.io.IOException;
import java.io.Reader;
/**
* A reader that deals with escape sequences in RNC files (\x{xx}) and keeps track of their positions to build correct
* token ranges in the lexer.
* <p/>
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 05.08.2007
*/
class EscapePreprocessor extends FilterReader {
private final TIntArrayList myQueuedChars;
private final TIntIntHashMap myLengthMap;
private int myOffset;
public EscapePreprocessor(Reader reader, int startOffset, TIntIntHashMap map) {
super(reader);
myOffset = startOffset;
myQueuedChars = new TIntArrayList();
myLengthMap = map;
}
@Override
public int read(char cbuf[], int off, int len) throws IOException {
final int i = read();
if (i == -1) {
return -1;
}
cbuf[off] = (char)i; // not really efficient, but acceptable since we're usually not having to deal with megabytes of RNC files...
return 1;
}
@Override
public int read() throws IOException {
if (myQueuedChars.size() > 0) {
return consume();
}
final int i = super.read();
if (i == -1) {
return -1;
}
myOffset++;
switch (i) {
case '\r':
assert false : "Unexpected newline character"; // IDEA document's are supposed to newlines normalized to \n
if (peek() == '\n') {
consume();
myLengthMap.put(myOffset - 1, 2);
}
case '\n':
return '\u0000';
case '\\':
int n = 0;
int x;
while ((x = peek()) == 'x') {
n++;
}
if (n > 0 && x == '{') {
n++;
} else {
return i;
}
int value = 0;
while (isHexChar((char)(x = peek()))) {
n++;
value <<= 4;
value |= Character.digit(x, 16);
}
if (x == '}') {
n++;
}
consume(n);
myLengthMap.put(myOffset - 1, n);
myOffset += n;
if (value <= 0xFFFF) {
return value;
}
myQueuedChars.add(Utf16.surrogate2(value));
return Utf16.surrogate1(value);
}
return i;
}
private static boolean isHexChar(char i) {
if (Character.isDigit(i)) return true;
final char c = Character.toLowerCase(i);
return c >= 'a' && c <= 'f';
}
private int consume() {
if (myQueuedChars.size() > 0) {
return myQueuedChars.remove(0);
}
return -1;
}
private void consume(int n) {
myQueuedChars.remove(0, n);
}
private int peek() throws IOException {
final int i = super.read();
if (i == -1) {
return -1;
}
myQueuedChars.add(i);
return i;
}
}
@@ -0,0 +1,420 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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.
*/
/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 3.0 */
package org.intellij.plugins.relaxNG.compact.lexer;
import org.kohsuke.rngom.parse.compact.CharStream;
import org.kohsuke.rngom.parse.compact.EOFException;
/**
* An implementation of interface CharStream, where the stream is assumed to
* contain only ASCII characters (without unicode processing).
*/
@SuppressWarnings({ "ALL" })
public class SimpleCharStream implements CharStream
{
int bufsize;
int available;
int tokenBegin;
public int bufpos = -1;
protected int bufline[];
protected int bufcolumn[];
protected int column = 0;
protected int line = 1;
protected boolean prevCharIsCR = false;
protected boolean prevCharIsLF = false;
protected java.io.Reader inputStream;
protected char[] buffer;
protected int maxNextCharInd = 0;
protected int inBuf = 0;
protected void ExpandBuff(boolean wrapAround)
{
char[] newbuffer = new char[bufsize + 2048];
int newbufline[] = new int[bufsize + 2048];
int newbufcolumn[] = new int[bufsize + 2048];
try
{
if (wrapAround)
{
System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
System.arraycopy(buffer, 0, newbuffer,
bufsize - tokenBegin, bufpos);
buffer = newbuffer;
System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
bufline = newbufline;
System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
bufcolumn = newbufcolumn;
maxNextCharInd = (bufpos += (bufsize - tokenBegin));
}
else
{
System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
buffer = newbuffer;
System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
bufline = newbufline;
System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
bufcolumn = newbufcolumn;
maxNextCharInd = (bufpos -= tokenBegin);
}
}
catch (Throwable t)
{
throw new Error(t.getMessage());
}
bufsize += 2048;
available = bufsize;
tokenBegin = 0;
}
protected void FillBuff() throws EOFException
{
if (maxNextCharInd == available)
{
if (available == bufsize)
{
if (tokenBegin > 2048)
{
bufpos = maxNextCharInd = 0;
available = tokenBegin;
}
else if (tokenBegin < 0)
bufpos = maxNextCharInd = 0;
else
ExpandBuff(false);
}
else if (available > tokenBegin)
available = bufsize;
else if ((tokenBegin - available) < 2048)
ExpandBuff(true);
else
available = tokenBegin;
}
int i;
try {
if ((i = inputStream.read(buffer, maxNextCharInd,
available - maxNextCharInd)) == -1)
{
inputStream.close();
throw new java.io.IOException();
}
else
maxNextCharInd += i;
return;
}
catch(java.io.IOException e) {
--bufpos;
backup(0);
if (tokenBegin == -1)
tokenBegin = bufpos;
throw new EOFException();
}
}
public char BeginToken() throws EOFException
{
tokenBegin = -1;
char c = readChar();
tokenBegin = bufpos;
return c;
}
protected void UpdateLineColumn(char c)
{
column++;
if (prevCharIsLF)
{
prevCharIsLF = false;
line += (column = 1);
}
else if (prevCharIsCR)
{
prevCharIsCR = false;
if (c == '\n')
{
prevCharIsLF = true;
}
else
line += (column = 1);
}
switch (c)
{
case '\r' :
prevCharIsCR = true;
break;
case '\n' :
prevCharIsLF = true;
break;
case '\t' :
column--;
column += (8 - (column & 07));
break;
default :
break;
}
bufline[bufpos] = line;
bufcolumn[bufpos] = column;
}
public char readChar() throws EOFException
{
if (inBuf > 0)
{
--inBuf;
if (++bufpos == bufsize)
bufpos = 0;
return buffer[bufpos];
}
if (++bufpos >= maxNextCharInd)
FillBuff();
char c = buffer[bufpos];
UpdateLineColumn(c);
return (c);
}
/**
* @deprecated
* @see #getEndColumn
*/
public int getColumn() {
return bufcolumn[bufpos];
}
/**
* @deprecated
* @see #getEndLine
*/
public int getLine() {
return bufline[bufpos];
}
public int getEndColumn() {
return bufcolumn[bufpos];
}
public int getEndLine() {
return bufline[bufpos];
}
public int getBeginColumn() {
return bufcolumn[tokenBegin];
}
public int getBeginLine() {
return bufline[tokenBegin];
}
public void backup(int amount) {
inBuf += amount;
if ((bufpos -= amount) < 0)
bufpos += bufsize;
}
public SimpleCharStream(java.io.Reader dstream, int startline,
int startcolumn, int buffersize)
{
inputStream = dstream;
line = startline;
column = startcolumn - 1;
available = bufsize = buffersize;
buffer = new char[buffersize];
bufline = new int[buffersize];
bufcolumn = new int[buffersize];
}
public SimpleCharStream(java.io.Reader dstream, int startline,
int startcolumn)
{
this(dstream, startline, startcolumn, 4096);
}
public SimpleCharStream(java.io.Reader dstream)
{
this(dstream, 1, 1, 4096);
}
public void ReInit(java.io.Reader dstream, int startline,
int startcolumn, int buffersize)
{
inputStream = dstream;
line = startline;
column = startcolumn - 1;
if (buffer == null || buffersize != buffer.length)
{
available = bufsize = buffersize;
buffer = new char[buffersize];
bufline = new int[buffersize];
bufcolumn = new int[buffersize];
}
prevCharIsLF = prevCharIsCR = false;
tokenBegin = inBuf = maxNextCharInd = 0;
bufpos = -1;
}
public void ReInit(java.io.Reader dstream, int startline,
int startcolumn)
{
ReInit(dstream, startline, startcolumn, 4096);
}
public void ReInit(java.io.Reader dstream)
{
ReInit(dstream, 1, 1, 4096);
}
public SimpleCharStream(java.io.InputStream dstream, int startline,
int startcolumn, int buffersize)
{
this(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
}
public SimpleCharStream(java.io.InputStream dstream, int startline,
int startcolumn)
{
this(dstream, startline, startcolumn, 4096);
}
public SimpleCharStream(java.io.InputStream dstream)
{
this(dstream, 1, 1, 4096);
}
public void ReInit(java.io.InputStream dstream, int startline,
int startcolumn, int buffersize)
{
ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
}
public void ReInit(java.io.InputStream dstream)
{
ReInit(dstream, 1, 1, 4096);
}
public void ReInit(java.io.InputStream dstream, int startline,
int startcolumn)
{
ReInit(dstream, startline, startcolumn, 4096);
}
public String GetImage()
{
if (bufpos >= tokenBegin)
return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
else
return new String(buffer, tokenBegin, bufsize - tokenBegin) +
new String(buffer, 0, bufpos + 1);
}
public char[] GetSuffix(int len)
{
char[] ret = new char[len];
if ((bufpos + 1) >= len)
System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
else
{
System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
len - bufpos - 1);
System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
}
return ret;
}
public void Done()
{
buffer = null;
bufline = null;
bufcolumn = null;
}
/**
* Method to adjust line and column numbers for the start of a token.
*/
public void adjustBeginLineColumn(int newLine, int newCol)
{
int start = tokenBegin;
int len;
if (bufpos >= tokenBegin)
{
len = bufpos - tokenBegin + inBuf + 1;
}
else
{
len = bufsize - tokenBegin + bufpos + 1 + inBuf;
}
int i = 0, j = 0, k = 0;
int nextColDiff = 0, columnDiff = 0;
while (i < len &&
bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
{
bufline[j] = newLine;
nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
bufcolumn[j] = newCol + columnDiff;
columnDiff = nextColDiff;
i++;
}
if (i < len)
{
bufline[j] = newLine++;
bufcolumn[j] = newCol + columnDiff;
while (i++ < len)
{
if (bufline[j = start % bufsize] != bufline[++start % bufsize])
bufline[j] = newLine++;
else
bufline[j] = newLine;
}
}
line = bufline[j];
column = bufcolumn[j];
}
}
@@ -0,0 +1,156 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.parser;
import org.intellij.plugins.relaxNG.compact.RncElementTypes;
import static org.intellij.plugins.relaxNG.compact.RncTokenTypes.*;
import com.intellij.lang.PsiBuilder;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 09.08.2007
*/
public abstract class AbstractParsing {
protected static final TokenSet LA_INCLUDE_CONTENT = TokenSet.orSet(TokenSet.create(
KEYWORD_DIV, KEYWORD_START), IDENTIFIERS);
protected static final TokenSet LA_GRAMMAR_CONTENT = TokenSet.orSet(TokenSet.create(
KEYWORD_INCLUDE), LA_INCLUDE_CONTENT);
protected static final TokenSet ATTR_OR_ELEMENT = TokenSet.create(
KEYWORD_ATTRIBUTE, KEYWORD_ElEMENT);
protected static final TokenSet CONTENT = TokenSet.create(
KEYWORD_LIST, KEYWORD_MIXED);
protected static final TokenSet LA_DATATYPE = TokenSet.create(
KEYWORD_STRING, KEYWORD_TOKEN);
protected static final TokenSet LA_DECL = TokenSet.create(
KEYWORD_DATATYPES, KEYWORD_NAMESPACE, KEYWORD_DEFAULT);
protected static final TokenSet NS_URI_LITERAL = TokenSet.create(KEYWORD_INHERIT, LITERAL);
protected static final TokenSet ASSIGN_METHOD = TokenSet.create(EQ, CHOICE_EQ, INTERLEAVE_EQ);
protected final PsiBuilder myBuilder;
public AbstractParsing(PsiBuilder builder) {
myBuilder = builder;
}
protected final PsiBuilder.Marker begin() {
final PsiBuilder.Marker marker = myBuilder.mark();
advance();
return marker;
}
protected final boolean matches(TokenSet set) {
if (set.contains(currentToken())) {
advance();
return true;
}
return false;
}
protected final boolean matches(IElementType t) {
if (t == currentToken()) {
advance();
return true;
}
return false;
}
protected final void match(IElementType token, String msg) {
if (!matches(token)) {
error(msg);
advance();
}
}
protected final void match(TokenSet set, String msg) {
if (!matches(set)) {
error(msg);
advance();
}
}
protected final void error(String s) {
myBuilder.error(s);
}
protected final void advance() {
myBuilder.advanceLexer();
}
protected final IElementType currentToken() {
final IElementType token = myBuilder.getTokenType();
if (isName(token)) {
final PsiBuilder.Marker marker = myBuilder.mark();
makeName();
if (myBuilder.getTokenType() == LBRACKET) {
skipAnnotation(marker, RncElementTypes.ANNOTATION_ELEMENT);
return currentToken();
} else {
marker.rollbackTo();
}
} else if (token == LBRACKET) {
final PsiBuilder.Marker marker = myBuilder.mark();
skipAnnotation(marker, RncElementTypes.ANNOTATION);
return currentToken();
} else if (token == GTGT) {
final PsiBuilder.Marker marker = myBuilder.mark();
advance();
if (isName(myBuilder.getTokenType())) {
makeName();
if (myBuilder.getTokenType() == LBRACKET) {
skipAnnotation(marker, RncElementTypes.FORWARD_ANNOTATION);
return currentToken();
}
}
marker.done(RncElementTypes.FORWARD_ANNOTATION);
return currentToken();
}
return token;
}
protected static boolean isName(IElementType token) {
return IDENTIFIER_OR_KEYWORD.contains(token) || token == PREFIXED_NAME;
}
private void skipAnnotation(PsiBuilder.Marker marker, IElementType annotationType) {
final boolean b = myBuilder.getTokenType() == LBRACKET;
advance();
assert b;
while (!myBuilder.eof() && currentToken() != RBRACKET) {
advance();
}
if (myBuilder.getTokenType() == RBRACKET) {
advance();
}
marker.done(annotationType);
}
protected final void makeName() {
final PsiBuilder.Marker name = myBuilder.mark();
advance();
name.done(RncElementTypes.NAME);
}
}
@@ -0,0 +1,178 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.parser;
import org.intellij.plugins.relaxNG.compact.RncElementTypes;
import static org.intellij.plugins.relaxNG.compact.RncTokenTypes.*;
import com.intellij.lang.PsiBuilder;
import com.intellij.psi.tree.IElementType;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 09.08.2007
*/
public abstract class DeclarationParsing extends AbstractParsing {
public DeclarationParsing(PsiBuilder builder) {
super(builder);
}
protected void parseTopLevel() {
while (!myBuilder.eof() && LA_DECL.contains(currentToken())) {
parseDecl(myBuilder);
}
if (LA_GRAMMAR_CONTENT.contains(currentToken())) {
final PsiBuilder.Marker marker = myBuilder.mark();
parseGrammarContents();
marker.done(RncElementTypes.GRAMMAR_PATTERN);
} else if (currentToken() == KEYWORD_GRAMMAR) {
parsePattern();
} else {
final PsiBuilder.Marker marker = myBuilder.mark();
while (!myBuilder.eof()) {
if (!parsePattern()) {
break;
}
}
marker.done(RncElementTypes.GRAMMAR_PATTERN);
}
}
protected abstract boolean parsePattern();
protected void parseGrammarContents() {
while (LA_GRAMMAR_CONTENT.contains(currentToken())) {
parseGrammarContent(true);
}
}
private void parseIncludeContents() {
while (LA_INCLUDE_CONTENT.contains(currentToken())) {
parseGrammarContent(false);
}
}
private void parseGrammarContent(boolean allowInclude) {
final IElementType t = currentToken();
if (t == KEYWORD_START) {
parseStart();
} else if (t == KEYWORD_DIV) {
parseDiv();
} else if (allowInclude && t == KEYWORD_INCLUDE) {
parseInclude();
} else if (IDENTIFIERS.contains(t)) {
parseDefine();
} else {
error("Unexpected token");
advance();
}
}
private void parseDefine() {
final PsiBuilder.Marker marker = begin();
match(ASSIGN_METHOD, "'=', '|=' or '&=' expected");
if (!parsePattern()) {
error("Pattern expected");
}
marker.done(RncElementTypes.DEFINE);
}
private void parseInclude() {
final PsiBuilder.Marker marker = begin();
parseAnyUriLiteral();
parseInherit();
if (matches(LBRACE)) {
parseIncludeContents();
match(RBRACE, "'}' expected");
}
marker.done(RncElementTypes.INCLUDE);
}
protected final void parseAnyUriLiteral() {
match(LITERAL, "URI literal expected");
}
protected final void parseInherit() {
if (matches(KEYWORD_INHERIT)) {
match(EQ, "'=' expected");
match(IDENTIFIER_OR_KEYWORD, "Identifier expected");
}
}
private void parseDiv() {
final PsiBuilder.Marker marker = begin();
parseBracedGrammarContents();
marker.done(RncElementTypes.DIV);
}
private void parseStart() {
final PsiBuilder.Marker marker = begin();
match(ASSIGN_METHOD, "'=', '|=' or '&=' expected");
if (!parsePattern()) {
error("Pattern expected");
}
marker.done(RncElementTypes.START);
}
protected void parseBracedGrammarContents() {
match(LBRACE, "'{' expected");
parseGrammarContents();
match(RBRACE, "'}' expected");
}
protected void parseDecl(PsiBuilder builder) {
final IElementType t = builder.getTokenType();
if (t == KEYWORD_NAMESPACE) {
parseNamespaceDecl(false);
} else if (t == KEYWORD_DEFAULT) {
parseNamespaceDecl(true);
} else if (t == KEYWORD_DATATYPES) {
parseDataTypesDecl();
}
}
private void parseDataTypesDecl() {
final PsiBuilder.Marker marker = begin();
match(IDENTIFIER_OR_KEYWORD, "Identifier expected");
match(EQ, "'=' expected");
parseNsUriLiteral();
marker.done(RncElementTypes.DATATYPES_DECL);
}
private void parseNamespaceDecl(boolean isDefault) {
final PsiBuilder.Marker marker = begin();
if (isDefault) {
match(KEYWORD_NAMESPACE, "'namespace' expected");
matches(IDENTIFIER_OR_KEYWORD);
} else {
match(IDENTIFIER_OR_KEYWORD, "Identifier expected");
}
match(EQ, "'=' expected");
parseNsUriLiteral();
marker.done(RncElementTypes.NS_DECL);
}
private void parseNsUriLiteral() {
match(NS_URI_LITERAL, "Namespace URI or 'inherit' expected");
}
}
@@ -0,0 +1,88 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.parser;
import org.intellij.plugins.relaxNG.compact.RncElementTypes;
import static org.intellij.plugins.relaxNG.compact.RncTokenTypes.*;
import com.intellij.lang.PsiBuilder;
import com.intellij.psi.tree.IElementType;
public class NameClassParsing extends AbstractParsing {
public NameClassParsing(PsiBuilder builder) {
super(builder);
}
public boolean parseNameClass() {
PsiBuilder.Marker marker = myBuilder.mark();
if (!parseNameClassPart()) {
marker.drop();
return false;
}
if (currentToken() == PIPE) {
do {
advance();
if (!parseNameClassPart()) {
error("NameClass expected");
}
} while (currentToken() == PIPE);
marker.done(RncElementTypes.NAME_CLASS_CHOICE);
} else {
marker.drop();
}
return true;
}
private boolean parseNameClassPart() {
final IElementType t = currentToken();
PsiBuilder.Marker marker = myBuilder.mark();
if (IDENTIFIER_OR_KEYWORD.contains(t)) {
advance();
} else if (PREFIXED_NAME == t) { // CName
makeName();
} else if (STAR == t) { // anyName
advance();
parseExceptNameClass();
} else if (PREFIXED_STAR == t) { // nsName
makeName();
parseExceptNameClass();
} else if (LPAREN == t) {
advance();
if (parseNameClass()) {
match(RPAREN, "')' expected");
}
} else {
marker.drop();
return false;
}
marker.done(RncElementTypes.NAME_CLASS);
return true;
}
private void parseExceptNameClass() {
if (MINUS == currentToken()) {
final PsiBuilder.Marker marker = begin();
if (!parseNameClass()) {
error("NameClass expected");
}
marker.done(RncElementTypes.EXCEPT_NAME_CLASS);
}
}
}
@@ -0,0 +1,191 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.parser;
import org.intellij.plugins.relaxNG.compact.RncElementTypes;
import static org.intellij.plugins.relaxNG.compact.RncTokenTypes.*;
import com.intellij.lang.PsiBuilder;
import com.intellij.psi.tree.IElementType;
import gnu.trove.THashMap;
import gnu.trove.TObjectHashingStrategy;
import java.util.Map;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 09.08.2007
*/
public class PatternParsing extends DeclarationParsing {
@SuppressWarnings({ "unchecked" })
protected static final Map<IElementType, IElementType> TOKEN_MAP =
new THashMap<IElementType, IElementType>(TObjectHashingStrategy.IDENTITY);
static {
TOKEN_MAP.put(COMMA, RncElementTypes.SEQUENCE);
TOKEN_MAP.put(PIPE, RncElementTypes.CHOICE);
TOKEN_MAP.put(AND, RncElementTypes.INTERLEAVE);
TOKEN_MAP.put(STAR, RncElementTypes.ZERO_OR_MORE);
TOKEN_MAP.put(PLUS, RncElementTypes.ONE_OR_MORE);
TOKEN_MAP.put(QUEST, RncElementTypes.OPTIONAL);
}
private final NameClassParsing myNameClassParsing;
public PatternParsing(PsiBuilder builder) {
super(builder);
myNameClassParsing = new NameClassParsing(builder);
}
public void parse() {
parseTopLevel();
}
protected boolean parsePattern() {
PsiBuilder.Marker marker = myBuilder.mark();
if (!parseQuantifiedPattern()) {
marker.drop();
return false;
}
while (BINARY_OPS.contains(currentToken())) {
IElementType t;
if (BINARY_OPS.contains(t = currentToken())) {
do {
advance();
if (!parseQuantifiedPattern()) {
error("Pattern expected");
}
} while (currentToken() == t);
marker.done(TOKEN_MAP.get(t));
marker = marker.precede();
}
}
marker.drop();
return true;
}
private boolean parseQuantifiedPattern() {
final PsiBuilder.Marker marker = myBuilder.mark();
if (!parseSinglePattern()) {
marker.drop();
return false;
}
final IElementType t = currentToken();
if (matches(QUANTIFIER_OPS)) {
marker.done(TOKEN_MAP.get(t));
} else {
marker.drop();
}
return true;
}
private boolean parseSinglePattern() {
final PsiBuilder.Marker marker = myBuilder.mark();
if (matches(ATTR_OR_ELEMENT)) {
if (!myNameClassParsing.parseNameClass()) {
error("Name class expected");
marker.drop();
return false;
}
parseBracedPattern();
marker.done(RncElementTypes.PATTERN);
} else if (matches(KEYWORD_LIST)) {
parseBracedPattern();
marker.done(RncElementTypes.LIST_PATTERN);
} else if (matches(KEYWORD_MIXED)) {
parseBracedPattern();
marker.done(RncElementTypes.MIXED_PATTERN);
} else if (matches(KEYWORD_EXTERNAL)) {
parseAnyUriLiteral();
parseInherit();
marker.done(RncElementTypes.EXTERNAL_REF);
} else if (matches(KEYWORD_NOT_ALLOWED)) {
marker.done(RncElementTypes.NOT_ALLOWED_PATTERN);
} else if (matches(KEYWORD_TEXT)) {
marker.done(RncElementTypes.TEXT_PATTERN);
} else if (matches(KEYWORD_EMPTY)) {
marker.done(RncElementTypes.EMPTY_PATTERN);
} else if (matches(KEYWORD_PARENT)) {
match(IDENTIFIERS, "Identifier expected");
marker.done(RncElementTypes.PARENT_REF);
} else if (matches(KEYWORD_GRAMMAR)) {
parseBracedGrammarContents();
marker.done(RncElementTypes.GRAMMAR_PATTERN);
} else if (matches(LPAREN)) {
if (!parsePattern()) {
error("Pattern expected");
}
match(RPAREN, "')' expected");
marker.done(RncElementTypes.GROUP_PATTERN);
} else if (matches(IDENTIFIERS)) {
marker.done(RncElementTypes.REF_PATTERN);
} else if (matches(LA_DATATYPE)) {
parseDatatype();
marker.done(RncElementTypes.DATATYPE_PATTERN);
} else if (currentToken() == PREFIXED_NAME) {
makeName();
parseDatatype();
marker.done(RncElementTypes.DATATYPE_PATTERN);
} else if (matches(LITERAL)) {
marker.done(RncElementTypes.DATATYPE_PATTERN);
} else {
marker.drop();
return false;
}
return true;
}
private void parseDatatype() {
if (currentToken() == LITERAL) {
advance();
} else if (matches(LBRACE)) {
parseParams();
if (matches(MINUS)) {
if (!parsePattern()) {
error("Pattern expected");
}
}
match(RBRACE, "'}' expected");
}
}
private void parseBracedPattern() {
match(LBRACE, "'{' expected");
if (!parsePattern()) {
error("Pattern expected");
}
match(RBRACE, "'}' expected");
}
private void parseParams() {
final IElementType t = currentToken();
if (t != RBRACE) {
do {
final PsiBuilder.Marker marker = myBuilder.mark();
match(IDENTIFIER_OR_KEYWORD, "Identifier expected");
match(EQ, "'=' expected");
match(LITERAL, "Literal expected");
marker.done(RncElementTypes.PARAM);
} while (IDENTIFIER_OR_KEYWORD.contains(currentToken()));
}
}
}
@@ -0,0 +1,50 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.parser;
import org.intellij.plugins.relaxNG.compact.RncElementTypes;
import com.intellij.lang.ASTNode;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.PsiParser;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 07.08.2007
*/
public class RncParser implements PsiParser {
@NotNull
public ASTNode parse(IElementType root, PsiBuilder builder) {
final PsiBuilder.Marker fileMarker = builder.mark();
final PsiBuilder.Marker docMarker = builder.mark();
new PatternParsing(builder).parse();
while (!builder.eof()) {
builder.error("Unexpected token");
builder.advanceLexer();
}
docMarker.done(RncElementTypes.DOCUMENT);
fileMarker.done(root);
return builder.getTreeBuilt();
}
}
@@ -0,0 +1,30 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi;
import com.intellij.psi.PsiComment;
import org.jetbrains.annotations.Nullable;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 24.08.2007
*/
public interface RncAnnotation extends RncElement, PsiComment {
@Nullable
RncName getNameElement();
}
@@ -0,0 +1,30 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi;
import com.intellij.psi.PsiNamedElement;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 16.08.2007
*/
public interface RncDecl extends RncElement, PsiNamedElement {
String getPrefix();
String getDeclaredNamespace();
}
@@ -0,0 +1,32 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi;
import org.intellij.plugins.relaxNG.model.Define;
import com.intellij.psi.PsiNamedElement;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 13.08.2007
*/
public interface RncDefine extends RncPattern, PsiNamedElement, Define<RncPattern, RncElement> {
@Nullable
RncPattern getPattern();
}
@@ -0,0 +1,27 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi;
import org.intellij.plugins.relaxNG.model.Div;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 24.08.2007
*/
public interface RncDiv extends RncElement, Div<RncElement> {
}
@@ -0,0 +1,27 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi;
import com.intellij.psi.PsiElement;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 10.08.2007
*/
public interface RncElement extends PsiElement {
}
@@ -0,0 +1,76 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
public class RncElementVisitor extends PsiElementVisitor {
@Override
public final void visitElement(PsiElement element) {
if (element instanceof RncElement) {
visitElement((RncElement)element);
} else {
superVisitElement(element);
}
}
protected void superVisitElement(PsiElement element) {
super.visitElement(element);
}
public void visitElement(RncElement element) {
super.visitElement(element);
}
public void visitInclude(RncInclude include) {
visitElement(include);
}
public void visitDiv(RncDiv div) {
visitElement(div);
}
public void visitRef(RncRef pattern) {
visitElement(pattern);
}
public void visitParentRef(RncParentRef pattern) {
visitElement(pattern);
}
public void visitDefine(RncDefine pattern) {
visitElement(pattern);
}
public void visitGrammar(RncGrammar pattern) {
visitElement(pattern);
}
public void visitName(RncName name) {
visitElement(name);
}
public void visitAnnotation(RncAnnotation annotation) {
visitElement(annotation);
}
public void visitExternalRef(RncExternalRef ref) {
visitElement(ref);
}
}
@@ -0,0 +1,26 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 11.08.2007
*/
public interface RncExternalRef extends RncFileReference {
}
@@ -0,0 +1,32 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 11.08.2007
*/
public interface RncFile extends PsiFile {
RncDecl[] getDeclarations();
@Nullable
RncGrammar getGrammar();
}
@@ -0,0 +1,35 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi;
import com.intellij.openapi.util.TextRange;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 29.08.2007
*/
public interface RncFileReference extends RncElement {
@Nullable
RncFile getReferencedFile();
@Nullable
String getFileReference();
TextRange getReferenceRange();
}
@@ -0,0 +1,31 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi;
import org.intellij.plugins.relaxNG.model.Grammar;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 13.08.2007
*/
public interface RncGrammar extends RncElement, Grammar<RncPattern, RncElement> {
@Nullable
RncPattern getStart();
}
@@ -0,0 +1,31 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi;
import org.intellij.plugins.relaxNG.model.Include;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 11.08.2007
*/
public interface RncInclude extends RncFileReference, Include<RncElement, RncDefine> {
@NotNull
RncDefine[] getOverrides();
}
@@ -0,0 +1,33 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 14.08.2007
*/
public interface RncName extends RncElement {
@Nullable
String getPrefix();
@NotNull
String getLocalPart();
}
@@ -0,0 +1,26 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 14.08.2007
*/
public interface RncNsDecl extends RncDecl {
boolean isDefault();
}
@@ -0,0 +1,25 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 13.08.2007
*/
public interface RncParentRef extends RncRef {
}
@@ -0,0 +1,27 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi;
import org.intellij.plugins.relaxNG.model.Pattern;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 05.09.2007
*/
public interface RncPattern extends RncElement, Pattern<RncElement> {
}
@@ -0,0 +1,34 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi;
import org.intellij.plugins.relaxNG.model.Ref;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 11.08.2007
*/
public interface RncRef extends RncPattern, Ref<RncDefine, RncElement> {
@Nullable
RncDefine getPattern();
@Nullable
String getReferencedName();
}
@@ -0,0 +1,32 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi.impl;
import org.intellij.plugins.relaxNG.compact.psi.RncFile;
import com.intellij.openapi.util.Key;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 13.08.2007
*/
public interface FollowFileHint {
Key<FollowFileHint> KEY = Key.create("FollowFileHint");
public boolean doFollow(RncFile file);
}
@@ -0,0 +1,227 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi.impl;
import org.intellij.plugins.relaxNG.compact.RncFileType;
import org.intellij.plugins.relaxNG.compact.RncTokenTypes;
import org.intellij.plugins.relaxNG.compact.psi.*;
import org.intellij.plugins.relaxNG.compact.psi.util.EscapeUtil;
import org.intellij.plugins.relaxNG.compact.psi.util.RenameUtil;
import org.intellij.plugins.relaxNG.model.Define;
import org.intellij.plugins.relaxNG.model.resolve.DefinitionResolver;
import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider;
import com.intellij.codeInsight.daemon.QuickFixProvider;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.Set;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 13.08.2007
*/
class PatternReference extends PsiReferenceBase.Poly<RncRef> implements Function<Define, ResolveResult>,
QuickFixProvider<PatternReference>, EmptyResolveMessageProvider {
public PatternReference(RncRef ref) {
super(ref);
}
public TextRange getRangeInElement() {
final ASTNode node = findNameNode();
if (node == null) return TextRange.from(0, 0);
final int offset = myElement.getTextOffset();
return TextRange.from(offset - myElement.getTextRange().getStartOffset(), node.getTextLength());
}
private ASTNode findNameNode() {
final ASTNode node = myElement.getNode();
assert node != null;
return node.findChildByType(RncTokenTypes.IDENTIFIERS);
}
@Nullable
public PsiElement resolve() {
final ResolveResult[] results = multiResolve(false);
return results.length == 1 ? results[0].getElement() : null;
}
@NotNull
public ResolveResult[] multiResolve(boolean incompleteCode) {
final RncGrammar scope = getScope();
if (scope == null) {
return ResolveResult.EMPTY_ARRAY;
}
final Set<Define> set = DefinitionResolver.resolve(scope, getCanonicalText());
if (set == null || set.size() == 0) return ResolveResult.EMPTY_ARRAY;
return ContainerUtil.map2Array(set, ResolveResult.class, this);
}
public ResolveResult fun(Define rncDefine) {
final PsiElement element = rncDefine.getPsiElement();
return element != null ? new PsiElementResolveResult(element) : new ResolveResult() {
@Nullable
public PsiElement getElement() {
return null;
}
public boolean isValidResult() {
return false;
}
};
}
@Nullable
protected RncGrammar getScope() {
return PsiTreeUtil.getParentOfType(myElement, RncGrammar.class, true, PsiFile.class);
}
public String getCanonicalText() {
final ASTNode node = findNameNode();
return node != null ? EscapeUtil.unescapeText(node) : "";
}
public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
final ASTNode newNode = RenameUtil.createIdentifierNode(getElement().getManager(), newElementName);
final ASTNode nameNode = findNameNode();
nameNode.getTreeParent().replaceChild(nameNode, newNode);
return getElement();
}
public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
throw new UnsupportedOperationException();
}
@NotNull
public Object[] getVariants() {
final RncGrammar scope = getScope();
if (scope == null) {
return ResolveResult.EMPTY_ARRAY;
}
final Map<String, Set<Define>> map = DefinitionResolver.getAllVariants(scope);
if (map == null || map.size() == 0) return ArrayUtil.EMPTY_OBJECT_ARRAY;
return ContainerUtil.mapNotNull(map.values(), new Function<Set<Define>, Object>() {
public Object fun(Set<Define> defines) {
return defines.size() == 0 ? null : defines.iterator().next().getPsiElement();
}
}).toArray();
}
public boolean isSoft() {
return false;
}
public String getUnresolvedMessagePattern() {
return "Unresolved pattern reference ''{0}''";
}
public void registerQuickfix(HighlightInfo info, final PatternReference reference) {
if (reference.getScope() == null) {
return;
}
QuickFixAction.registerQuickFixAction(info, new CreatePatternFix(reference));
}
static class CreatePatternFix implements IntentionAction {
private final PatternReference myReference;
public CreatePatternFix(PatternReference reference) {
myReference = reference;
}
@NotNull
public String getText() {
return "Create Pattern '" + myReference.getCanonicalText() + "'";
}
@NotNull
public String getFamilyName() {
return "Create Pattern";
}
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return myReference.getElement().isValid() && myReference.getScope() != null;
}
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
final RncFile rncfile = (RncFile)PsiFileFactory.getInstance(myReference.getElement().getProject()).createFileFromText("dummy.rnc", RncFileType.getInstance(), "dummy = xxx");
final RncGrammar grammar = rncfile.getGrammar();
assert grammar != null;
final RncDefine def = (RncDefine)grammar.getFirstChild();
final RncGrammar scope = myReference.getScope();
assert scope != null;
assert def != null;
final RncDefine e = (RncDefine)scope.add(def);
// ensures proper escaping (start -> \start)
def.setName(myReference.getCanonicalText());
final SmartPsiElementPointer<RncDefine> p = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(e);
final ASTNode blockNode = e.getParent().getNode();
assert blockNode != null;
final ASTNode newNode = e.getNode();
assert newNode != null;
e.getManager().getCodeStyleManager().reformatNewlyAddedElement(blockNode, newNode);
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument());
final RncDefine d = p.getElement();
assert d != null;
final RncElement definition = d.getPattern();
assert definition != null;
final int offset = definition.getTextRange().getStartOffset();
editor.getCaretModel().moveToOffset(offset);
editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
editor.getDocument().deleteString(offset, definition.getTextRange().getEndOffset());
}
public boolean startInWriteAction() {
return true;
}
}
}
@@ -0,0 +1,50 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi.impl;
import org.intellij.plugins.relaxNG.compact.psi.RncAnnotation;
import org.intellij.plugins.relaxNG.compact.psi.RncElementVisitor;
import org.intellij.plugins.relaxNG.compact.psi.RncName;
import com.intellij.lang.ASTNode;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 24.08.2007
*/
public class RncAnnotationImpl extends RncElementImpl implements RncAnnotation {
public RncAnnotationImpl(ASTNode node) {
super(node);
}
public void accept(@NotNull RncElementVisitor visitor) {
visitor.visitAnnotation(this);
}
public IElementType getTokenType() {
return getNode().getElementType();
}
@Nullable
public RncName getNameElement() {
return findChildByClass(RncName.class);
}
}
@@ -0,0 +1,88 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi.impl;
import org.intellij.plugins.relaxNG.compact.RncTokenTypes;
import org.intellij.plugins.relaxNG.compact.psi.RncDecl;
import org.intellij.plugins.relaxNG.compact.psi.RncElementVisitor;
import org.intellij.plugins.relaxNG.compact.psi.util.EscapeUtil;
import org.intellij.plugins.relaxNG.compact.psi.util.RenameUtil;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 16.08.2007
*/
public class RncDeclImpl extends RncElementImpl implements RncDecl {
public RncDeclImpl(ASTNode node) {
super(node);
}
public String getPrefix() {
final ASTNode ns = findIdentifierNode();
return ns != null ? EscapeUtil.unescapeText(ns) : null;
}
public String getDeclaredNamespace() {
final ASTNode ns = getNode().findChildByType(RncTokenTypes.LITERAL);
return ns != null ? EscapeUtil.parseLiteralValue(ns) : null;
}
@Override
public int getTextOffset() {
final ASTNode ns = findIdentifierNode();
if (ns != null) {
return ns.getStartOffset();
}
return super.getTextOffset();
}
private ASTNode findIdentifierNode() {
// namespace text = "..." is valid - "text" is parsed as a keyword though
final ASTNode node = getNode().findChildByType(RncTokenTypes.IDENTIFIERS);
if (node == null) {
final ASTNode[] nodes = getNode().getChildren(RncTokenTypes.KEYWORDS);
if (nodes.length > 1) {
return nodes[1];
}
}
return node;
}
@Override
public String getName() {
final String s = getPrefix();
return s != null ? s : "";
}
public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException {
final ASTNode node = findIdentifierNode();
if (node == null) return this;
node.getTreeParent().replaceChild(node, RenameUtil.createIdentifierNode(getManager(), name));
return this;
}
public void accept(@NotNull RncElementVisitor visitor) {
visitor.visitElement(this);
}
}
@@ -0,0 +1,171 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.Iconable;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiReferenceBase;
import com.intellij.psi.meta.PsiMetaData;
import com.intellij.psi.meta.PsiMetaOwner;
import com.intellij.psi.meta.PsiPresentableMetaData;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import org.intellij.plugins.relaxNG.compact.RncTokenTypes;
import org.intellij.plugins.relaxNG.compact.psi.*;
import org.intellij.plugins.relaxNG.compact.psi.util.EscapeUtil;
import org.intellij.plugins.relaxNG.compact.psi.util.RenameUtil;
import org.intellij.plugins.relaxNG.model.Define;
import org.intellij.plugins.relaxNG.model.resolve.DefinitionResolver;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.Map;
import java.util.Set;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 13.08.2007
*/
public class RncDefineImpl extends RncElementImpl implements RncDefine, PsiMetaOwner {
public RncDefineImpl(ASTNode node) {
super(node);
}
public void accept(@NotNull RncElementVisitor visitor) {
visitor.visitDefine(this);
}
public void accept(Visitor visitor) {
visitor.visitDefine(this);
}
@Override
public String getName() {
final ASTNode node = getNameNode();
return EscapeUtil.unescapeText(node);
}
public PsiElement getNameElement() {
return getNameNode().getPsi();
}
@NotNull
public ASTNode getNameNode() {
final ASTNode node = getNode().findChildByType(RncTokenTypes.IDENTIFIERS);
assert node != null;
return node;
}
public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException {
final ASTNode node = getNameNode();
node.getTreeParent().replaceChild(node, RenameUtil.createIdentifierNode(getManager(), name));
return this;
}
@Nullable
public RncPattern getPattern() {
return findChildByClass(RncPattern.class);
}
public PsiReference getReference() {
if (getParent() instanceof RncInclude) {
final TextRange range = TextRange.from(0, getNameNode().getTextLength());
return new PsiReferenceBase<RncDefine>(this, range, true) {
public PsiElement resolve() {
return RncDefineImpl.this;
}
@NotNull
public Object[] getVariants() {
final RncInclude parent = (RncInclude)getParent();
final RncFile referencedFile = parent.getReferencedFile();
if (referencedFile == null) {
return EMPTY_ARRAY;
}
final RncGrammar grammar = referencedFile.getGrammar();
if (grammar == null) {
return EMPTY_ARRAY;
}
final Map<String, Set<Define>> map = DefinitionResolver.getAllVariants(grammar);
if (map != null) {
return map.keySet().toArray();
}
return EMPTY_ARRAY;
}
};
}
return super.getReference();
}
@Nullable
public Icon getIcon(int flags) {
return IconLoader.findIcon("/nodes/property.png");
}
public boolean isMetaEnough() {
return true;
}
@Nullable
public PsiMetaData getMetaData() {
return new MyMetaData();
}
private class MyMetaData implements PsiMetaData, PsiPresentableMetaData {
/*public boolean processDeclarations(PsiElement context, PsiScopeProcessor processor, PsiSubstitutor substitutor, PsiElement lastElement, PsiElement place) {
return false;
}*/
@Nullable
public Icon getIcon() {
return RncDefineImpl.this.getIcon(Iconable.ICON_FLAG_CLOSED);
}
public String getTypeName() {
return "Pattern Definition";
}
public PsiElement getDeclaration() {
return RncDefineImpl.this;
}
@NonNls
public String getName(PsiElement context) {
return RncDefineImpl.this.getName();
}
@NonNls
public String getName() {
return RncDefineImpl.this.getName();
}
public void init(PsiElement element) {
}
public Object[] getDependences() {
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
}
}
@@ -0,0 +1,43 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi.impl;
import org.intellij.plugins.relaxNG.compact.psi.RncDiv;
import org.intellij.plugins.relaxNG.compact.psi.RncElementVisitor;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 24.08.2007
*/
public class RncDivImpl extends RncElementImpl implements RncDiv {
public RncDivImpl(ASTNode node) {
super(node);
}
public void accept(@NotNull RncElementVisitor visitor) {
visitor.visitDiv(this);
}
@Override
public void accept(Visitor visitor) {
visitor.visitDiv(this);
}
}
@@ -0,0 +1,82 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi.impl;
import org.intellij.plugins.relaxNG.compact.psi.RncElementVisitor;
import org.intellij.plugins.relaxNG.compact.psi.RncGrammar;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.meta.MetaRegistry;
import com.intellij.psi.meta.PsiMetaData;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.xml.XmlDocument;
import com.intellij.psi.xml.XmlProlog;
import com.intellij.psi.xml.XmlTag;
import com.intellij.xml.XmlNSDescriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class RncDocument extends RncElementImpl implements XmlDocument {
public RncDocument(ASTNode node) {
super(node);
}
public XmlNSDescriptor getDefaultNSDescriptor(String namespace, boolean strict) {
return null;
}
public XmlProlog getProlog() {
return null;
}
@Nullable
public XmlTag getRootTag() {
return null;
}
public XmlNSDescriptor getRootTagNSDescriptor() {
return null;
}
public boolean processElements(PsiElementProcessor processor, PsiElement place) {
return false;
}
@Nullable
public PsiMetaData getMetaData() {
return MetaRegistry.getMeta(this);
}
public boolean isMetaEnough() {
return true;
}
public RncGrammar getGrammar() {
return findChildByClass(RncGrammar.class);
}
@Override
@NotNull
protected <T> T[] findChildrenByClass(Class<T> aClass) {
return super.findChildrenByClass(aClass);
}
public void accept(@NotNull RncElementVisitor visitor) {
visitor.visitElement(this);
}
}
@@ -0,0 +1,138 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi.impl;
import org.intellij.plugins.relaxNG.compact.RncElementTypes;
import org.intellij.plugins.relaxNG.compact.psi.RncElement;
import org.intellij.plugins.relaxNG.compact.psi.RncElementVisitor;
import org.intellij.plugins.relaxNG.model.CommonElement;
import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.ResolveState;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.tree.TokenSet;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
public abstract class RncElementImpl extends ASTWrapperPsiElement implements RncElement, CommonElement<RncElement> {
private static final TokenSet GRAMMAR_CONTENT = TokenSet.create(
RncElementTypes.START,
RncElementTypes.DEFINE, RncElementTypes.DIV,
RncElementTypes.GRAMMAR_PATTERN, RncElementTypes.PATTERN,
RncElementTypes.INCLUDE
);
public RncElementImpl(ASTNode node) {
super(node);
}
public String toString() {
return getNode().getElementType().toString();
}
@Override
public void delete() throws IncorrectOperationException {
getNode().getTreeParent().removeChild(getNode());
}
@Override
public PsiElement add(@NotNull PsiElement psiElement) throws IncorrectOperationException {
final ASTNode astNode = psiElement.getNode();
assert astNode != null;
getNode().addChild(astNode);
final PsiElement r = getNode().getLastChildNode().getPsi();
assert r.getClass() == psiElement.getClass();
return r;
}
@Override
public PsiElement addBefore(@NotNull PsiElement psiElement, PsiElement anchor) throws IncorrectOperationException {
final ASTNode child = psiElement.getNode();
assert child != null;
final ASTNode anchorNode = anchor.getNode();
assert anchorNode != null;
getNode().addChild(child, anchorNode);
final PsiElement r = anchorNode.getTreePrev().getPsi();
assert r.getClass() == psiElement.getClass();
return r;
}
@Override
public PsiElement addAfter(@NotNull PsiElement element, PsiElement anchor) throws IncorrectOperationException {
final ASTNode astNode = anchor.getNode();
assert astNode != null;
final ASTNode node = astNode.getTreeNext();
if (node == null) {
return add(element);
} else {
return addBefore(element, node.getPsi());
}
}
public final void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof RncElementVisitor) {
accept((RncElementVisitor)visitor);
} else {
visitor.visitElement(this);
}
}
@Override
public boolean processDeclarations(@NotNull PsiScopeProcessor processor, @NotNull ResolveState substitutor, PsiElement lastParent, @NotNull PsiElement place) {
final ASTNode astNode = getNode();
final ASTNode[] children = astNode.getChildren(GRAMMAR_CONTENT);
processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, this);
for (ASTNode element : children) {
if (!processor.execute(element.getPsi(), substitutor)) {
return false;
}
}
processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, null);
return true;
}
public abstract void accept(@NotNull RncElementVisitor visitor);
public void accept(Visitor visitor) {
visitor.visitElement(this);
}
public void acceptChildren(Visitor visitor) {
final PsiElement[] elements = getChildren();
//noinspection ForLoopReplaceableByForEach
for (int i = 0; i < elements.length; i++) {
PsiElement element = elements[i];
if (element instanceof CommonElement) {
((CommonElement)element).accept(visitor);
}
}
}
public RncElement getPsiElement() {
return this;
}
}
@@ -0,0 +1,38 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi.impl;
import org.intellij.plugins.relaxNG.compact.psi.RncElementVisitor;
import org.intellij.plugins.relaxNG.compact.psi.RncExternalRef;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 10.08.2007
*/
public class RncExternalRefImpl extends RncFileReferenceImpl implements RncExternalRef {
public RncExternalRefImpl(ASTNode node) {
super(node);
}
public void accept(@NotNull RncElementVisitor visitor) {
visitor.visitExternalRef(this);
}
}
@@ -0,0 +1,126 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi.impl;
import com.intellij.extapi.psi.PsiFileBase;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.ResolveState;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.xml.XmlDocument;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.IncorrectOperationException;
import org.intellij.plugins.relaxNG.compact.RncElementTypes;
import org.intellij.plugins.relaxNG.compact.RncFileType;
import org.intellij.plugins.relaxNG.compact.RngCompactLanguage;
import org.intellij.plugins.relaxNG.compact.psi.RncDecl;
import org.intellij.plugins.relaxNG.compact.psi.RncFile;
import org.intellij.plugins.relaxNG.compact.psi.RncGrammar;
import org.jetbrains.annotations.NotNull;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 01.08.2007
*/
public class RncFileImpl extends PsiFileBase implements RncFile, XmlFile {
private static final TokenSet DECLS = TokenSet.create(RncElementTypes.NS_DECL, RncElementTypes.DATATYPES_DECL);
public RncFileImpl(FileViewProvider viewProvider) {
super(viewProvider, RngCompactLanguage.INSTANCE);
}
@NotNull
public FileType getFileType() {
return RncFileType.getInstance();
}
@NotNull
public XmlDocument getDocument() {
// this needs to be a seperate child element because of com.intellij.util.xml.impl.ExternalChangeProcessor.visitDocumentChanged()
final XmlDocument document = findChildByClass(XmlDocument.class);
assert document != null;
return document;
}
@Override
public boolean processDeclarations(@NotNull PsiScopeProcessor processor, @NotNull ResolveState substitutor, PsiElement lastParent, @NotNull PsiElement place) {
//processor.handleEvent(JavaScopeProcessorEvent.SET_CURRENT_FILE_CONTEXT, this);
try {
final ASTNode docNode = getDocument().getNode();
assert docNode != null;
final ASTNode[] nodes = docNode.getChildren(DECLS);
for (ASTNode node : nodes) {
if (!processor.execute(node.getPsi(), substitutor)) {
return false;
}
}
final RncGrammar grammar = getGrammar();
if (grammar != null) {
return grammar.processDeclarations(processor, substitutor, lastParent, place);
} else {
return true;
}
} finally {
//processor.handleEvent(JavaScopeProcessorEvent.SET_CURRENT_FILE_CONTEXT, null);
}
}
@Override
public PsiElement add(@NotNull PsiElement element) throws IncorrectOperationException {
return getDocument().add(element);
}
@Override
public PsiElement addAfter(@NotNull PsiElement element, PsiElement anchor) throws IncorrectOperationException {
return getDocument().addAfter(element, anchor);
}
@Override
public PsiElement addBefore(@NotNull PsiElement element, PsiElement anchor) throws IncorrectOperationException {
return getDocument().addBefore(element, anchor);
}
public boolean processElements(PsiElementProcessor processor, PsiElement place) {
return false;
}
public GlobalSearchScope getFileResolveScope() {
return ProjectScope.getAllScope(getProject());
}
@Override
public String toString() {
return getClass().getSimpleName() + ":" + getName();
}
public RncDecl[] getDeclarations() {
return ((RncDocument)getDocument()).findChildrenByClass(RncDecl.class);
}
public RncGrammar getGrammar() {
final XmlDocument document = getDocument();
return ((RncDocument)document).getGrammar();
}
}
@@ -0,0 +1,99 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi.impl;
import org.intellij.plugins.relaxNG.compact.RncFileType;
import org.intellij.plugins.relaxNG.compact.RncTokenTypes;
import org.intellij.plugins.relaxNG.compact.psi.RncFile;
import org.intellij.plugins.relaxNG.compact.psi.RncFileReference;
import org.intellij.plugins.relaxNG.compact.psi.util.EscapeUtil;
import org.intellij.plugins.relaxNG.references.FileReferenceUtil;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference;
import com.intellij.psi.ResolveState;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.xml.util.XmlUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 29.08.2007
*/
abstract class RncFileReferenceImpl extends RncElementImpl implements RncFileReference {
public RncFileReferenceImpl(ASTNode node) {
super(node);
}
@NotNull
@Override
@SuppressWarnings({ "SSBasedInspection" })
public PsiReference[] getReferences() {
final ASTNode literal = getNode().findChildByType(RncTokenTypes.LITERAL);
if (literal == null) return PsiReference.EMPTY_ARRAY;
final String s = literal.getText();
final FileReferenceSet set =
new FileReferenceSet(s.substring(1, s.length() - 1), this,
getReferenceRange().getStartOffset(),
null, true, false);
return FileReferenceUtil.restrict(set, FileReferenceUtil.byType(RncFileType.getInstance()));
}
public RncFile getReferencedFile() {
final String href = getFileReference();
if (href != null) {
final PsiFile file = XmlUtil.findRelativeFile(href, getContainingFile());
if (file instanceof RncFile) {
return (RncFile)file;
}
}
return null;
}
@Nullable
public String getFileReference() {
final ASTNode element = getNode().findChildByType(RncTokenTypes.LITERAL);
if (element == null) return null;
final String s = EscapeUtil.unescapeText(element);
return s.substring(1, s.length() - 1);
}
public TextRange getReferenceRange() {
final ASTNode literal = getNode().findChildByType(RncTokenTypes.LITERAL);
if (literal == null) return TextRange.from(0, 0);
final int startInElement = literal.getStartOffset() - getTextOffset() + 1;
return TextRange.from(startInElement, literal.getTextLength() - 2);
}
@Override
public boolean processDeclarations(@NotNull PsiScopeProcessor processor, @NotNull ResolveState substitutor, PsiElement lastParent, @NotNull PsiElement place) {
final FollowFileHint hint = processor.getHint(FollowFileHint.KEY);
final RncFile file = getReferencedFile();
if (file != null && hint != null && hint.doFollow(file)) {
file.processDeclarations(processor, substitutor, lastParent, place);
}
return true;
}
}
@@ -0,0 +1,62 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi.impl;
import org.intellij.plugins.relaxNG.compact.RncElementTypes;
import org.intellij.plugins.relaxNG.compact.RncTokenTypes;
import org.intellij.plugins.relaxNG.compact.psi.RncElementVisitor;
import org.intellij.plugins.relaxNG.compact.psi.RncGrammar;
import org.intellij.plugins.relaxNG.compact.psi.RncPattern;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 13.08.2007
*/
public class RncGrammarImpl extends RncElementImpl implements RncGrammar {
public RncGrammarImpl(ASTNode node) {
super(node);
}
public void accept(@NotNull RncElementVisitor visitor) {
visitor.visitGrammar(this);
}
public void accept(Visitor visitor) {
visitor.visitGrammar(this);
}
public RncPattern getStart() {
final ASTNode node = getNode().findChildByType(RncElementTypes.START);
return node != null ? (RncPattern)node.getPsi() : null;
}
@Override
public PsiElement add(@NotNull PsiElement psiElement) throws IncorrectOperationException {
final PsiElement rbrace = findChildByType(RncTokenTypes.RBRACE);
// TODO: fix block psi
if (rbrace != null) {
return addBefore(psiElement, rbrace);
}
return super.add(psiElement);
}
}
@@ -0,0 +1,69 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi.impl;
import org.intellij.plugins.relaxNG.compact.psi.RncDefine;
import org.intellij.plugins.relaxNG.compact.psi.RncElementVisitor;
import org.intellij.plugins.relaxNG.compact.psi.RncInclude;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.ResolveState;
import com.intellij.psi.scope.PsiScopeProcessor;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 10.08.2007
*/
public class RncIncludeImpl extends RncFileReferenceImpl implements RncInclude {
public RncIncludeImpl(ASTNode node) {
super(node);
}
@Override
public boolean processDeclarations(@NotNull PsiScopeProcessor processor, @NotNull ResolveState substitutor, PsiElement lastParent, @NotNull PsiElement place) {
final PsiElement[] children = getChildren();
for (PsiElement child : children) {
if (!processor.execute(child, substitutor)) {
return false;
}
}
return super.processDeclarations(processor, substitutor, lastParent, place);
}
public void accept(@NotNull RncElementVisitor visitor) {
visitor.visitInclude(this);
}
@Override
public void accept(Visitor visitor) {
visitor.visitInclude(this);
}
public PsiFile getInclude() {
return getReferencedFile();
}
@NotNull
public RncDefine[] getOverrides() {
// TODO: DIVs?
return findChildrenByClass(RncDefine.class);
}
}
@@ -0,0 +1,277 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi.impl;
import org.intellij.plugins.relaxNG.compact.RncElementTypes;
import org.intellij.plugins.relaxNG.compact.RncTokenTypes;
import org.intellij.plugins.relaxNG.compact.psi.*;
import org.intellij.plugins.relaxNG.compact.psi.util.EscapeUtil;
import org.intellij.plugins.relaxNG.compact.psi.util.RenameUtil;
import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider;
import com.intellij.codeInsight.daemon.QuickFixProvider;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.lookup.LookupItem;
import com.intellij.codeInsight.template.*;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.scope.BaseScopeProcessor;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 14.08.2007
*/
public class RncNameImpl extends RncElementImpl implements RncName, PsiReference,
EmptyResolveMessageProvider, QuickFixProvider<RncNameImpl> {
private enum Kind {
NAMESPACE, DATATYPES
}
private final Kind myKind;
public RncNameImpl(ASTNode node) {
super(node);
final IElementType parent = node.getTreeParent().getElementType();
if (parent == RncElementTypes.DATATYPE_PATTERN) {
myKind = Kind.DATATYPES;
} else {
myKind = Kind.NAMESPACE;
}
}
@Nullable
public String getPrefix() {
final String[] parts = EscapeUtil.unescapeText(getNode()).split(":", 2);
return parts.length == 2 ? parts[0] : null;
}
@NotNull
public String getLocalPart() {
final String[] parts = EscapeUtil.unescapeText(getNode()).split(":", 2);
return parts.length == 1 ? parts[0] : parts[1];
}
@Override
public void accept(@NotNull RncElementVisitor visitor) {
visitor.visitName(this);
}
@Override
public PsiReference getReference() {
return getPrefix() == null ? null : this;
}
public PsiElement getElement() {
return this;
}
public TextRange getRangeInElement() {
return TextRange.from(0, getText().indexOf(':'));
}
@Nullable
public PsiElement resolve() {
final MyResolver resolver = new MyResolver(getPrefix(), myKind);
getContainingFile().processDeclarations(resolver, ResolveState.initial(), this, this);
return resolver.getResult();
}
public String getCanonicalText() {
return getRangeInElement().substring(getText());
}
public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
final ASTNode node = getNode();
final ASTNode child = RenameUtil.createPrefixedNode(getManager(), newElementName, getLocalPart());
node.getTreeParent().replaceChild(node, child);
return child.getPsi();
}
public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
throw new UnsupportedOperationException();
}
public boolean isReferenceTo(PsiElement element) {
return element instanceof RncElement && Comparing.equal(resolve(), element);
}
@NotNull
public Object[] getVariants() {
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
public boolean isSoft() {
final String prefix = getPrefix();
return "xsd".equals(prefix) || "xml".equals(prefix);
}
public String getUnresolvedMessagePattern() {
return "Unresolved namespace prefix ''{0}''";
}
public void registerQuickfix(HighlightInfo info, final RncNameImpl reference) {
if (reference.getPrefix() == null) return; // huh?
QuickFixAction.registerQuickFixAction(info, new CreateDeclFix(reference));
}
private static class MyResolver extends BaseScopeProcessor {
private final String myPrefix;
private final Kind myKind;
private PsiElement myResult;
public MyResolver(String prefix, Kind kind) {
myPrefix = prefix;
myKind = kind;
}
public boolean execute(PsiElement element, ResolveState substitutor) {
final ASTNode node = element.getNode();
if (node == null) return true;
if (!(element instanceof RncDecl)) {
return false;
}
final IElementType type = node.getElementType();
if (myKind == Kind.NAMESPACE && type == RncElementTypes.NS_DECL) {
if (checkDecl(element)) return false;
} else if (myKind == Kind.DATATYPES && type == RncElementTypes.DATATYPES_DECL) {
if (checkDecl(element)) return false;
}
return true;
}
private boolean checkDecl(PsiElement element) {
if (myPrefix.equals(((RncDecl)element).getPrefix())) {
myResult = element;
return true;
}
return false;
}
public PsiElement getResult() {
return myResult;
}
}
public static class CreateDeclFix implements IntentionAction {
private final RncNameImpl myReference;
public CreateDeclFix(RncNameImpl reference) {
myReference = reference;
}
@NotNull
public String getText() {
return getFamilyName() + " '" + myReference.getPrefix() + "'";
}
@NotNull
public String getFamilyName() {
return "Create " + myReference.myKind.name().toLowerCase() + " declaration";
}
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return myReference.isValid();
}
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
final String prefix = myReference.getPrefix();
final RncFile psiFile = (RncFile)PsiFileFactory.getInstance(myReference.getProject()).createFileFromText("dummy.rnc", myReference.myKind.name().toLowerCase() + " " + prefix + " = \"###\"");
final RncFile rncFile = (RncFile)myReference.getContainingFile();
final RncDecl[] declarations = rncFile.getDeclarations();
final RncDecl decl = psiFile.getDeclarations()[0];
final RncDecl e;
if (declarations.length > 0) {
e = (RncDecl)rncFile.addAfter(decl, declarations[declarations.length - 1]);
} else {
final RncGrammar rncGrammar = rncFile.getGrammar();
if (rncGrammar != null) {
e = (RncDecl)rncFile.addBefore(decl, rncGrammar);
} else {
e = (RncDecl)rncFile.add(decl);
}
}
final ASTNode blockNode = e.getParent().getNode();
assert blockNode != null;
final ASTNode newNode = e.getNode();
assert newNode != null;
e.getManager().getCodeStyleManager().reformatNewlyAddedElement(blockNode, newNode);
final SmartPsiElementPointer<RncDecl> p = SmartPointerManager.getInstance(project).createLazyPointer(e);
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument());
final RncDecl d = p.getElement();
assert d != null;
final PsiElement literal = d.getLastChild();
assert literal != null;
final ASTNode literalNode = literal.getNode();
assert literalNode != null;
assert literalNode.getElementType() == RncTokenTypes.LITERAL;
final int offset = literal.getTextRange().getStartOffset();
editor.getDocument().deleteString(literal.getTextRange().getStartOffset(), literal.getTextRange().getEndOffset());
final TemplateManager manager = TemplateManager.getInstance(project);
final Template t = manager.createTemplate("", "");
t.addTextSegment("\"");
final Expression expression = new Expression() {
public Result calculateResult(ExpressionContext context) {
return new TextResult("");
}
public Result calculateQuickResult(ExpressionContext context) {
return calculateResult(context);
}
public LookupItem[] calculateLookupItems(ExpressionContext context) {
return LookupItem.EMPTY_ARRAY;
}
};
t.addVariable("uri", expression, expression, true);
t.addTextSegment("\"");
t.addEndVariable();
editor.getCaretModel().moveToOffset(offset);
manager.startTemplate(editor, t);
}
public boolean startInWriteAction() {
return true;
}
}
}
@@ -0,0 +1,37 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi.impl;
import org.intellij.plugins.relaxNG.compact.RncTokenTypes;
import org.intellij.plugins.relaxNG.compact.psi.RncNsDecl;
import com.intellij.lang.ASTNode;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 14.08.2007
*/
public class RncNsDeclImpl extends RncDeclImpl implements RncNsDecl {
public RncNsDeclImpl(ASTNode node) {
super(node);
}
public boolean isDefault() {
return getNode().findChildByType(RncTokenTypes.KEYWORD_DEFAULT) != null;
}
}
@@ -0,0 +1,72 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi.impl;
import org.intellij.plugins.relaxNG.compact.psi.RncElementVisitor;
import org.intellij.plugins.relaxNG.compact.psi.RncGrammar;
import org.intellij.plugins.relaxNG.compact.psi.RncParentRef;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 11.08.2007
*/
public class RncParentRefImpl extends RncRefImpl implements RncParentRef {
public RncParentRefImpl(ASTNode node) {
super(node);
}
@Override // super asserts nameNode != null
public String getReferencedName() {
final ASTNode node = findNameNode();
return node == null ? null : super.getReferencedName();
}
@Override
public void accept(@NotNull RncElementVisitor visitor) {
visitor.visitParentRef(this);
}
@Override
public int getTextOffset() {
final ASTNode astNode = findNameNode();
return astNode != null ? astNode.getStartOffset() : getTextRange().getStartOffset();
}
@Override
@Nullable
public PsiReference getReference() {
return new PatternReference(this) {
@Override
protected RncGrammar getScope() {
final PsiElement scope = PsiTreeUtil.getParentOfType(getElement(), RncGrammar.class, true, PsiFile.class);
if (scope == null) {
return null;
}
return PsiTreeUtil.getParentOfType(scope, RncGrammar.class, true, PsiFile.class);
}
};
}
}
@@ -0,0 +1,70 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi.impl;
import org.intellij.plugins.relaxNG.compact.RncTokenTypes;
import org.intellij.plugins.relaxNG.compact.psi.RncDefine;
import org.intellij.plugins.relaxNG.compact.psi.RncElementVisitor;
import org.intellij.plugins.relaxNG.compact.psi.RncRef;
import org.intellij.plugins.relaxNG.compact.psi.util.EscapeUtil;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiReference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 11.08.2007
*/
public class RncRefImpl extends RncElementImpl implements RncRef {
public RncRefImpl(ASTNode node) {
super(node);
}
@Nullable
public RncDefine getPattern() {
final PsiReference ref = getReference();
// TODO: honor combine & return virtual element if multiResolve().length > 0
return ref instanceof PatternReference ? (RncDefine)ref.resolve() : null;
}
public String getReferencedName() {
final ASTNode node = findNameNode();
assert node != null;
return EscapeUtil.unescapeText(node);
}
protected ASTNode findNameNode() {
return getNode().findChildByType(RncTokenTypes.IDENTIFIERS);
}
@Override
public void accept(@NotNull RncElementVisitor visitor) {
visitor.visitRef(this);
}
public void accept(Visitor visitor) {
visitor.visitRef(this);
}
@Override
public PsiReference getReference() {
return new PatternReference(this);
}
}
@@ -0,0 +1,67 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi.util;
import org.intellij.plugins.relaxNG.compact.RncTokenTypes;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 13.08.2007
*/
public class EscapeUtil {
@SuppressWarnings({ "SSBasedInspection" })
public static String unescapeText(@NotNull PsiElement element) {
final ASTNode node = element.getNode();
if (node != null) {
return unescapeText(node);
} else {
return element.getText();
}
}
@SuppressWarnings({ "SSBasedInspection" })
public static String unescapeText(@NotNull ASTNode node) {
final String text = node.getText();
// TODO: unescape \x{xx} sequences
if (node.getElementType() == RncTokenTypes.ESCAPED_IDENTIFIER) {
assert text.charAt(0) == '\\';
return text.length() > 1 ? text.substring(1) : "";
} else {
return text;
}
}
public static String parseLiteralValue(ASTNode ns) {
return unquote(unescapeText(ns));
}
private static String unquote(String s) {
if (s.length() >= 6 && s.charAt(0) == s.charAt(1)) {
s = s.replace('\u0000', '\n');
return s.substring(3, s.length() - 3);
} else {
return s.substring(1, s.length() - 1);
}
}
}
@@ -0,0 +1,36 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi.util;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.util.NotNullFunction;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 13.08.2007
*/
public final class PsiFunction implements NotNullFunction<ASTNode, PsiElement> {
public static final PsiFunction INSTANCE = new PsiFunction();
@NotNull
public PsiElement fun(ASTNode astNode) {
return astNode.getPsi();
}
}
@@ -0,0 +1,111 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.psi.util;
import org.intellij.plugins.relaxNG.compact.RncElementTypes;
import org.intellij.plugins.relaxNG.compact.RncFileType;
import org.intellij.plugins.relaxNG.compact.RncTokenTypes;
import org.intellij.plugins.relaxNG.compact.RngCompactLanguage;
import org.intellij.plugins.relaxNG.compact.psi.RncFile;
import org.intellij.plugins.relaxNG.compact.psi.RncGrammar;
import com.intellij.lang.ASTNode;
import com.intellij.lang.LanguageParserDefinitions;
import com.intellij.lang.ParserDefinition;
import com.intellij.lexer.Lexer;
import com.intellij.psi.PsiFileFactory;
import com.intellij.psi.PsiManager;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 14.08.2007
*/
public class RenameUtil {
@NotNull
public static ASTNode createIdentifierNode(PsiManager manager, String name) throws IncorrectOperationException {
if (isKeyword(manager, name)) {
name = "\\" + name;
} else if (!isIdentifier(manager, name)) {
throw new IncorrectOperationException("Illegal identifier: " + name);
}
final PsiFileFactory f = PsiFileFactory.getInstance(manager.getProject());
final RncFile file = (RncFile)f.createFileFromText("dummy.rnc", RncFileType.getInstance(), name + " = bar");
final ASTNode astNode = findFirstGrammarNode(file);
final ASTNode newNode = astNode.findChildByType(RncTokenTypes.IDENTIFIERS);
assert newNode != null;
return newNode;
}
public static boolean isIdentifier(PsiManager manager, String name) {
return isTokenOfType(manager, name, RncTokenTypes.IDENTIFIER_OR_KEYWORD);
}
public static boolean isKeyword(PsiManager manager, String name) {
return isTokenOfType(manager, name, RncTokenTypes.KEYWORDS);
}
private static boolean isTokenOfType(PsiManager manager, String name, TokenSet set) {
final ParserDefinition definition = LanguageParserDefinitions.INSTANCE.forLanguage(RngCompactLanguage.INSTANCE);
assert definition != null;
final Lexer lexer = definition.createLexer(manager.getProject());
lexer.start(name, 0, name.length(), 0);
final IElementType t = lexer.getTokenType();
lexer.advance();
return lexer.getTokenType() == null && set.contains(t);
}
public static ASTNode createPrefixedNode(PsiManager manager, String prefix, String localPart) {
final PsiFileFactory f = PsiFileFactory.getInstance(manager.getProject());
final RncFile file = (RncFile)f.createFileFromText("dummy.rnc", RncFileType.getInstance(), "element " + prefix + ":" + localPart + " { text }");
final ASTNode node = findFirstGrammarNode(file);
final ASTNode nameClassNode = node.findChildByType(RncElementTypes.NAME_CLASS);
assert nameClassNode != null;
final ASTNode astNode = nameClassNode.findChildByType(RncElementTypes.NAME);
assert astNode != null;
return astNode;
}
@NotNull
private static ASTNode findFirstGrammarNode(RncFile file) {
final RncGrammar grammar = file.getGrammar();
assert grammar != null;
final ASTNode grammarNode = grammar.getNode();
assert grammarNode != null;
final ASTNode astNode = grammarNode.getFirstChildNode();
assert astNode != null;
return astNode;
}
public static ASTNode createLiteralNode(PsiManager manager, String content) {
final PsiFileFactory f = PsiFileFactory.getInstance(manager.getProject());
final RncFile file = (RncFile)f.createFileFromText("dummy.rnc", RncFileType.getInstance(), "include \"" + content + "\"");
final ASTNode include = findFirstGrammarNode(file);
final ASTNode literal = include.findChildByType(RncTokenTypes.LITERAL);
assert literal != null;
return literal;
}
}
@@ -0,0 +1,41 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.config;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 26.11.2007
*/
public abstract class NoNamespaceConfig implements ProjectComponent {
@Nullable
public abstract String getMapping(@NotNull PsiFile file);
public abstract VirtualFile getMappedFile(@NotNull PsiFile file);
public abstract void setMapping(@NotNull PsiFile file, @Nullable String location);
public static NoNamespaceConfig getInstance(@NotNull Project project) {
return project.getComponent(NoNamespaceConfig.class);
}
}
@@ -0,0 +1,175 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.config;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.editor.HectorComponentPanel;
import com.intellij.openapi.editor.HectorComponentPanelsProvider;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.pointers.VirtualFilePointer;
import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.xmlb.annotations.MapAnnotation;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 25.11.2007
*/
@State(
name = "NoNamespaceConfig.Mappings",
storages = { @Storage(
id = "other",
file = "$WORKSPACE_FILE$") })
class NoNamespaceConfigImpl extends NoNamespaceConfig implements PersistentStateComponent<NoNamespaceConfigImpl.Mappings> {
private final Map<VirtualFilePointer, VirtualFilePointer> myMappings = new HashMap<VirtualFilePointer, VirtualFilePointer>();
private final Project myProject;
NoNamespaceConfigImpl(Project project) {
myProject = project;
}
private VirtualFilePointer getMappedPointer(@NotNull PsiFile file) {
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile == null) return null;
final String url = virtualFile.getUrl();
for (VirtualFilePointer pointer : myMappings.keySet()) {
if (url.equals(pointer.getUrl())) {
return myMappings.get(pointer);
}
}
return null;
}
@Nullable
public String getMapping(@NotNull PsiFile file) {
final VirtualFilePointer pointer = getMappedPointer(file);
return pointer != null ? pointer.getUrl() : null;
}
public VirtualFile getMappedFile(@NotNull PsiFile file) {
final VirtualFilePointer url = getMappedPointer(file);
return url != null ? url.getFile() : null;
}
public void setMapping(@NotNull PsiFile file, String location) {
final VirtualFile virtualFile = file.getVirtualFile();
assert virtualFile != null;
final String url = virtualFile.getUrl();
final VirtualFilePointerManager manager = VirtualFilePointerManager.getInstance();
for (VirtualFilePointer pointer : myMappings.keySet()) {
if (url.equals(pointer.getUrl())) {
if (location == null) {
myMappings.remove(pointer);
return;
} else if (!location.equals(myMappings.get(pointer).getUrl())) {
myMappings.remove(pointer);
myMappings.put(pointer, manager.create(location, myProject, null));
return;
}
}
}
if (location != null) {
myMappings.put(manager.create(url, myProject, null), manager.create(location, myProject, null));
}
}
public void initComponent() {
}
public void disposeComponent() {
}
@NotNull
public String getComponentName() {
return "RELAX-NG.NoNamespaceConfig";
}
public void projectOpened() {
}
public void projectClosed() {
reset();
}
public Mappings getState() {
final HashMap<String, String> map = new HashMap<String, String>();
for (Map.Entry<VirtualFilePointer, VirtualFilePointer> entry : myMappings.entrySet()) {
map.put(entry.getKey().getUrl(), entry.getValue().getUrl());
}
return new Mappings(map);
}
public void loadState(Mappings state) {
reset();
final VirtualFilePointerManager manager = VirtualFilePointerManager.getInstance();
final Map<String, String> map = state.myMappings;
for (String file : map.keySet()) {
myMappings.put(manager.create(file, myProject, null), manager.create(map.get(file), myProject, null));
}
}
private void reset() {
myMappings.clear();
}
@SuppressWarnings({ "CanBeFinal", "UnusedDeclaration" })
public static class Mappings {
@MapAnnotation(surroundWithTag = false, entryTagName = "mapping", keyAttributeName = "file", valueAttributeName = "schema")
public Map<String, String> myMappings;
public Mappings() {
myMappings = new HashMap<String, String>();
}
Mappings(Map<String, String> map) {
myMappings = map;
}
}
public static class HectorProvider implements HectorComponentPanelsProvider {
@Nullable
public HectorComponentPanel createConfigurable(@NotNull PsiFile file) {
if (file instanceof XmlFile) {
try {
final XmlTag rootTag = ((XmlFile)file).getDocument().getRootTag();
if (rootTag.getNamespace().length() == 0) {
return new NoNamespaceConfigPanel(NoNamespaceConfig.getInstance(file.getProject()), file);
}
} catch (NullPointerException e) {
return null;
}
}
return null;
}
}
}
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.intellij.plugins.relaxNG.config.NoNamespaceConfigPanel">
<grid id="27dc6" binding="myRoot" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="687" height="96"/>
</constraints>
<properties/>
<border type="none" title="RELAX-NG Schema Association"/>
<children>
<component id="9c3ce" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="mySchemaFile">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false">
<minimum-size width="160" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<vspacer id="e4455">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
</children>
</grid>
<inspectionSuppressions>
<suppress inspection="NoLabelFor" id="9c3ce"/>
</inspectionSuppressions>
</form>
@@ -0,0 +1,133 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.config;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.editor.HectorComponentPanel;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.ui.ComponentWithBrowseButton;
import com.intellij.openapi.ui.TextComponentAccessor;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import org.intellij.plugins.relaxNG.compact.RncFileType;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.io.File;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 25.11.2007
*/
class NoNamespaceConfigPanel extends HectorComponentPanel {
private final NoNamespaceConfig myConfig;
private final PsiFile myFile;
private final String myMapping;
private TextFieldWithBrowseButton mySchemaFile;
private JPanel myRoot;
private boolean myDialogOpen;
NoNamespaceConfigPanel(NoNamespaceConfig noNamespaceConfig, PsiFile file) {
myConfig = noNamespaceConfig;
myFile = file;
myMapping = myConfig.getMapping(file);
final FileChooserDescriptor descriptor = new FileChooserDescriptor(true, false, false, false, false, false) {
public boolean isFileSelectable(VirtualFile file) {
final boolean b = super.isFileSelectable(file);
if (b) {
final FileType type = file.getFileType();
if (type != StdFileTypes.XML) {
return type == RncFileType.getInstance();
}
}
return b;
}
};
final Project project = file.getProject();
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile != null) {
final Module module = ProjectRootManager.getInstance(project).getFileIndex().getModuleForFile(virtualFile);
descriptor.putUserData(LangDataKeys.MODULE_CONTEXT, module);
}
// that's kind of a hack that ensures the Hector Panel stays open when selecting a file. otherwise it will close
// as soon as a file selected.
final ComponentWithBrowseButton.BrowseFolderActionListener<JTextField> actionListener =
new ComponentWithBrowseButton.BrowseFolderActionListener<JTextField>("Select Schema", "Select a RELAX-NG file to associate with the document",
mySchemaFile, project, descriptor, TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT) {
public void actionPerformed(ActionEvent e) {
myDialogOpen = true;
try {
super.actionPerformed(e);
} finally {
myDialogOpen = false;
}
}
};
mySchemaFile.addActionListener(actionListener);
}
public boolean canClose() {
return super.canClose() && !myDialogOpen;
}
public JComponent createComponent() {
return myRoot;
}
public boolean isModified() {
final String s = mySchemaFile.getText();
final String m = myMapping != null ? myMapping : "";
return !s.equals(m);
}
public void apply() throws ConfigurationException {
final String s = getMapping();
if (s != null) {
myConfig.setMapping(myFile, s);
} else {
myConfig.setMapping(myFile, null);
}
}
private String getMapping() {
final String s = mySchemaFile.getText().trim();
return s.length() > 0 ? VfsUtil.pathToUrl(s.replace(File.separatorChar, '/')) : null;
}
public void reset() {
mySchemaFile.setText(myMapping != null ? VfsUtil.urlToPath(myMapping).replace('/', File.separatorChar) : "");
}
public void disposeUIResources() {
// doesn't help - updating the validation needs a hard modification
// DaemonCodeAnalyzer.getInstance(myFile.getProject()).restart();
}
}
@@ -0,0 +1,55 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.config;
import com.intellij.ide.highlighter.XmlFileType;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.xml.XmlFile;
import com.intellij.xml.XmlSchemaProvider;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 22.11.2007
*/
public class NoNamespaceSchemaProvider extends XmlSchemaProvider {
@Nullable
public XmlFile getSchema(@NotNull @NonNls String url, @Nullable Module module, @NotNull PsiFile baseFile) {
if ("".equals(url)) {
final Project project = baseFile.getProject();
final VirtualFile file = NoNamespaceConfig.getInstance(project).getMappedFile(baseFile);
if (file == null) return null;
final PsiFile f = PsiManager.getInstance(project).findFile(file);
if (f instanceof XmlFile) {
return (XmlFile)f;
}
}
return null;
}
@Override
public boolean isAvailable(@NotNull XmlFile file) {
return file.getFileType() == XmlFileType.INSTANCE;
}
}
@@ -0,0 +1,191 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.intellij.plugins.relaxNG.convert.AdvancedDtdOptions">
<grid id="27dc6" binding="myRoot" layout-manager="GridLayoutManager" row-count="9" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="529" height="392"/>
</constraints>
<properties/>
<border type="none" title="DTD Input"/>
<children>
<component id="60570" class="javax.swing.JCheckBox" binding="myInlineAttlistCheckBox" default-binding="true">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&amp;inline-attlist"/>
<toolTipText value="Specifies not to generate definitions for attribute list declarations and instead move attributes declared in attribute list declarations into the definitions generated for element declarations. This is the default behavior when the output module is xsd. Otherwise, the default behaviour is as described in the -i no-inline-attlist parameter. "/>
</properties>
</component>
<component id="ee970" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="4bcfc"/>
<text value="&amp;colon-replacement:"/>
<toolTipText value="Replaces colons in element names by chars when constructing the names of definitions used to represent the element declarations and attribute list declarations in the DTD. Trang generates a definition for each element declaration and attlist declaration in the DTD. The name of the definition is based on the name of the element. In RELAX NG, the names of definitions cannot contain colons. However, in the DTD, the element name may contain a colon. By default, Trang will first try to use the element names without prefixes. If this causes a conflict, it will instead replace the colon by a legal name character (it try first to use a period). "/>
</properties>
</component>
<component id="4bcfc" class="javax.swing.JTextField" binding="myColonReplacement">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="c69bb" class="javax.swing.JLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="12ad0"/>
<text value="&amp;element-define:"/>
<toolTipText value="Specifies how to construct the name of the definition representing an element declaration from the name of the element. The name-pattern must contain exactly one percent character. This percent character is replaced by the name of element (after colon replacement) and the result is used as the name of the definition"/>
</properties>
</component>
<component id="12ad0" class="javax.swing.JTextField" binding="myElementDefine">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="b63cc" class="javax.swing.JLabel">
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="1" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="5576"/>
<text value="&amp;attlist-define:"/>
<toolTipText value="This specifies how to construct the name of the definition representing an attribute list declaration from the name of the element. The name-pattern must contain exactly one percent character. This percent character is replaced by the name of element (after colon replacement) and the result is used as the name of the definition. "/>
</properties>
</component>
<component id="5576" class="javax.swing.JTextField" binding="myAttlistDefine">
<constraints>
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="32a4e" class="javax.swing.JLabel">
<constraints>
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="bbb31"/>
<text value="a&amp;ny-name:"/>
<toolTipText value="Specifies the name of the definition generated for the content of elements declared in the DTD as having a content model of ANY."/>
</properties>
</component>
<component id="bbb31" class="javax.swing.JTextField" binding="myAnyName">
<constraints>
<grid row="4" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="62d5d" class="javax.swing.JCheckBox" binding="myStrictAnyCheckBox" default-binding="true">
<constraints>
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&amp;strict-any"/>
<toolTipText value="Preserves the exact semantics of ANY content models by using an explicit choice of references to all declared elements. By default, Trang uses a wildcard that allows any element. "/>
</properties>
</component>
<component id="b1561" class="javax.swing.JLabel">
<constraints>
<grid row="6" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="79c45"/>
<text value="ann&amp;otation-prefix:"/>
<toolTipText value="Default values are represented using an annotation attribute prefix:defaultValue where prefix is bound to http://relaxng.org/ns/compatibility/annotations/1.0 as defined by the RELAX NG DTD Compatibility Committee Specification. By default, Trang will use a for prefix unless that conflicts with a prefix used in the DTD. "/>
</properties>
</component>
<component id="79c45" class="javax.swing.JTextField" binding="myAnnotationPrefix">
<constraints>
<grid row="6" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="d14ca" class="javax.swing.JCheckBox" binding="myGenerateStartCheckBox" default-binding="true">
<constraints>
<grid row="7" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&amp;generate-start"/>
<toolTipText value="Specifies whether Trang should generate a start element. DTDs do not indicate what elements are allowed as document elements. Trang assumes that all elements that are defined but never referenced are allowed as document elements. "/>
</properties>
</component>
<grid id="c0da2" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="8" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none" title="Namespace Settings"/>
<children>
<component id="3e6e" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="577de"/>
<text value="&amp;Default:"/>
</properties>
</component>
<vspacer id="827e3">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="577de" class="javax.swing.JTextField" binding="myDefaultNS">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<scrollpane id="66236">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="18116" class="javax.swing.JTable" binding="myNamespaceMap">
<constraints/>
<properties>
<preferredScrollableViewportSize width="250" height="70"/>
</properties>
<clientProperties>
<terminateEditOnFocusLost class="java.lang.Boolean" value="true"/>
</clientProperties>
</component>
</children>
</scrollpane>
<grid id="f0444" binding="myToolbar" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints>
<grid row="1" column="2" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children/>
</grid>
</children>
</grid>
</children>
</grid>
<inspectionSuppressions>
<suppress inspection="NoLabelFor" id="66236"/>
</inspectionSuppressions>
</form>
@@ -0,0 +1,258 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.convert;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiRecursiveElementVisitor;
import com.intellij.psi.xml.XmlAttributeDecl;
import com.intellij.psi.xml.XmlElementDecl;
import org.jetbrains.annotations.NonNls;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.*;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 18.11.2007
*/
public class AdvancedDtdOptions implements AdvancedOptions {
@NonNls
private static final String COLON_REPLACEMENT = "colon-replacement";
@NonNls
private static final String ELEMENT_DEFINE = "element-define";
@NonNls
private static final String ATTLIST_DEFINE = "attlist-define";
@NonNls
private static final String INLINE_ATTLIST = "inline-attlist";
@NonNls
private static final String ANY_NAME = "any-name";
@NonNls
private static final String STRICT_ANY = "strict-any";
@NonNls
private static final String ANNOTATION_PREFIX = "annotation-prefix";
@NonNls
private static final String GENERATE_START = "generate-start";
@NonNls
private static final String XMLNS = "xmlns";
private JComponent myRoot;
private JCheckBox myInlineAttlistCheckBox;
private JTextField myColonReplacement;
private JTextField myElementDefine;
private JTextField myAttlistDefine;
private JTextField myAnyName;
private JCheckBox myStrictAnyCheckBox;
private JTextField myAnnotationPrefix;
private JCheckBox myGenerateStartCheckBox;
private JTextField myDefaultNS;
private JTable myNamespaceMap;
private JPanel myToolbar;
public AdvancedDtdOptions() {
myInlineAttlistCheckBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
myAttlistDefine.setEnabled(false);
} else {
myAttlistDefine.setEnabled(true);
}
}
});
myNamespaceMap.setModel(new NamespaceMapModel());
myNamespaceMap.getColumnModel().getColumn(0).setMaxWidth((int)(new JLabel("Prefix").getPreferredSize().width * 1.2));
final DefaultActionGroup group = new DefaultActionGroup();
group.add(new AnAction(null, "Remove Entry", IconLoader.findIcon("/general/remove.png")) {
public void update(AnActionEvent e) {
if (myNamespaceMap.getModel().getRowCount() == 0 || myNamespaceMap.getSelectedRow() == -1) {
e.getPresentation().setEnabled(false);
} else {
e.getPresentation().setEnabled(true);
}
}
public void actionPerformed(AnActionEvent e) {
((NamespaceMapModel)myNamespaceMap.getModel()).removeRow(myNamespaceMap.getSelectedRow());
}
});
final ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, false);
myToolbar.add(toolbar.getComponent());
}
public JComponent getRoot() {
return myRoot;
}
public Map<String, ?> getOptions() {
final HashMap<String, Object> map = new LinkedHashMap<String, Object>();
map.put(INLINE_ATTLIST, myInlineAttlistCheckBox.isSelected());
setText(map, COLON_REPLACEMENT, myColonReplacement);
setText(map, ELEMENT_DEFINE, myElementDefine);
setText(map, ATTLIST_DEFINE, myAttlistDefine);
setText(map, ANY_NAME, myAnyName);
if (myStrictAnyCheckBox.isSelected()) {
map.put(STRICT_ANY, Boolean.TRUE);
}
setText(map, ANNOTATION_PREFIX, myAnnotationPrefix);
map.put(GENERATE_START, myGenerateStartCheckBox.isSelected());
if (myDefaultNS.getText().trim().length() > 0) {
map.put(XMLNS, myDefaultNS.getText() );
}
final List<String[]> data = ((NamespaceMapModel)myNamespaceMap.getModel()).getData();
for (String[] parts : data) {
map.put(XMLNS + ":" + parts[0], parts[1]);
}
return map;
}
private static void setText(HashMap<String, Object> map, String option, JTextField field) {
final String colonReplacement = field.getText();
if (colonReplacement != null && colonReplacement.trim().length() > 0) {
map.put(option, colonReplacement);
}
}
public void setOptions(Map<String, ?> inputOptions) {
if (inputOptions.containsKey(COLON_REPLACEMENT)) {
myColonReplacement.setText((String)inputOptions.get(COLON_REPLACEMENT));
}
myInlineAttlistCheckBox.setSelected(inputOptions.get(INLINE_ATTLIST) == Boolean.TRUE);
if (inputOptions.containsKey(ELEMENT_DEFINE)) {
myElementDefine.setText((String)inputOptions.get(ELEMENT_DEFINE));
}
if (inputOptions.containsKey(ATTLIST_DEFINE)) {
myAttlistDefine.setText((String)inputOptions.get(ATTLIST_DEFINE));
}
if (inputOptions.containsKey(ANY_NAME)) {
myAnyName.setText((String)inputOptions.get(ANY_NAME));
}
myStrictAnyCheckBox.setSelected(inputOptions.get(STRICT_ANY) == Boolean.TRUE);
if (inputOptions.containsKey(ANNOTATION_PREFIX)) {
myAnnotationPrefix.setText((String)inputOptions.get(ANNOTATION_PREFIX));
}
myGenerateStartCheckBox.setSelected(inputOptions.get(GENERATE_START) == Boolean.TRUE);
if (inputOptions.containsKey(XMLNS)) {
myDefaultNS.setText((String)inputOptions.get(XMLNS));
}
final NamespaceMapModel model = (NamespaceMapModel)myNamespaceMap.getModel();
final Set<String> set = inputOptions.keySet();
final String prefix = XMLNS + ":";
for (String s : set) {
if (s.startsWith(prefix)) {
model.addMapping(s.substring(prefix.length()), (String)inputOptions.get(s));
}
}
}
public static Map<String, ?> prepareNamespaceMap(Project project, VirtualFile firstFile) {
final PsiFile file = PsiManager.getInstance(project).findFile(firstFile);
if (file == null) {
return Collections.emptyMap();
}
final HashMap<String, Object> map = new LinkedHashMap<String, Object>();
file.accept(new PsiRecursiveElementVisitor() {
public void visitElement(PsiElement element) {
if (element instanceof XmlElementDecl) {
final String s = ((XmlElementDecl)element).getName();
if (s != null) {
final String[] parts = s.split(":");
if (parts.length > 1) {
map.put(XMLNS + ":" + parts[0], null);
}
}
} else if (element instanceof XmlAttributeDecl) {
final String s = ((XmlAttributeDecl)element).getName();
if (s != null) {
final String[] parts = s.split(":");
if (parts.length > 1) {
map.put(XMLNS + ":" + parts[0], null);
}
}
}
super.visitElement(element);
}
});
return map;
}
private static class NamespaceMapModel extends AbstractTableModel {
private final List<String[]> myList = new ArrayList<String[]>();
public String getColumnName(int column) {
return column == 0 ? "Prefix" : "URI";
}
public int getRowCount() {
return myList.size();
}
public int getColumnCount() {
return 2;
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == 1;
}
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
myList.get(rowIndex)[columnIndex] = (String)aValue;
}
public Object getValueAt(int rowIndex, int columnIndex) {
return myList.get(rowIndex)[columnIndex];
}
public void addMapping(String prefix, String uri) {
myList.add(new String[]{ prefix, uri });
fireTableRowsInserted(myList.size() - 1, myList.size() - 1);
}
public void removeRow(int row) {
myList.remove(row);
fireTableRowsDeleted(row - 1, row - 1);
}
public List<String[]> getData() {
return myList;
}
}
}
@@ -0,0 +1,33 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.convert;
import javax.swing.*;
import java.util.Map;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 19.11.2007
*/
public interface AdvancedOptions {
JComponent getRoot();
Map<String, ?> getOptions();
void setOptions(Map<String, ?> options);
}
@@ -0,0 +1,95 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.convert;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.Map;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 16.11.2007
*/
public class AdvancedOptionsDialog extends DialogWrapper {
private AdvancedOptions myInputOptions;
private AdvancedOptions myOutputOptions;
private Map<String,?> myInputOptions_;
private Map<String,?> myOutputOptions_;
protected AdvancedOptionsDialog(Project project, SchemaType inputType, SchemaType outputType) {
super(project, false);
setTitle("Advanced Conversion Options");
if (inputType == SchemaType.DTD) {
myInputOptions = new AdvancedDtdOptions();
}
if (outputType == SchemaType.XSD) {
myOutputOptions = new AdvancedXsdOptions();
}
init();
}
@Nullable
protected JComponent createCenterPanel() {
JComponent root;
if (myInputOptions != null && myOutputOptions != null) {
root = new JTabbedPane();
((JTabbedPane)root).addTab("Input", myInputOptions.getRoot());
((JTabbedPane)root).addTab("Output", myOutputOptions.getRoot());
} else if (myInputOptions != null) {
root = myInputOptions.getRoot();
} else {
root = myOutputOptions.getRoot();
}
return root;
}
public Map<String, ?> getInputOptions() {
if (myInputOptions != null) {
return myInputOptions.getOptions();
} else {
return myInputOptions_;
}
}
public Map<String, ?> getOutputOptions() {
if (myOutputOptions != null) {
return myOutputOptions.getOptions();
} else {
return myOutputOptions_;
}
}
public void setOptions(Map<String, ?> inputOptions, Map<String, ?> outputOptions) {
if (myInputOptions != null) {
myInputOptions.setOptions(inputOptions);
} else {
myInputOptions_ = inputOptions;
}
if (myOutputOptions != null) {
myOutputOptions.setOptions(outputOptions);
} else {
myOutputOptions_ = outputOptions;
}
}
}
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.intellij.plugins.relaxNG.convert.AdvancedXsdOptions">
<grid id="27dc6" binding="myRoot" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="335" height="128"/>
</constraints>
<properties/>
<border type="none" title="W3C XML Schema Output"/>
<children>
<vspacer id="bb5e1">
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="d49de" class="javax.swing.JLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="480bc"/>
<text value="&amp;any-process-contents"/>
<toolTipText value="Specifies the value for the processContents attribute of any elements. &#10;The default is skip (corresponding to RELAX NG semantics) unless the &#10;input format is dtd, in which case the default is strict (corresponding to &#10;DTD semantics). "/>
</properties>
</component>
<component id="272a3" class="javax.swing.JLabel">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="6d96a"/>
<text value="a&amp;ny-attribute-process-contents"/>
<toolTipText value="Specifies the value for the processContents attribute of any Attribute &#10;elements. The default is skip (corresponding to RELAX NG semantics). "/>
</properties>
</component>
<component id="480bc" class="com.intellij.openapi.ui.ComboBox" binding="myAnyProcessContents">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<model>
<item value="strict"/>
<item value="lax"/>
<item value="skip"/>
</model>
</properties>
</component>
<component id="6d96a" class="com.intellij.openapi.ui.ComboBox" binding="myAnyAttributeProcessContents">
<constraints>
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<model>
<item value="strict"/>
<item value="lax"/>
<item value="skip"/>
</model>
</properties>
</component>
<component id="1cd5c" class="javax.swing.JCheckBox" binding="myDisableAbstractElements" default-binding="true">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&amp;disable-abstract-elements"/>
<toolTipText value="Disables the use of abstract elements and subsitution groups &#10;in the generated XML Schema. This can also be controlled using &#10;an annotation attribute."/>
</properties>
</component>
</children>
</grid>
</form>
@@ -0,0 +1,70 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.convert;
import com.intellij.openapi.ui.ComboBox;
import org.jetbrains.annotations.NonNls;
import javax.swing.*;
import java.util.HashMap;
import java.util.Map;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 18.11.2007
*/
public class AdvancedXsdOptions implements AdvancedOptions {
@NonNls
private static final String DISABLE_ABSTRACT_ELEMENTS = "disable-abstract-elements";
@NonNls
private static final String ANY_PROCESS_CONTENTS = "any-process-contents";
@NonNls
private static final String ANY_ATTRIBUTE_PROCESS_CONTENTS = "any-attribute-process-contents";
private JComponent myRoot;
private JCheckBox myDisableAbstractElements;
private ComboBox myAnyProcessContents;
private ComboBox myAnyAttributeProcessContents;
public JComponent getRoot() {
return myRoot;
}
public Map<String, ?> getOptions() {
final Map<String, Object> strings = new HashMap<String, Object>();
if (myDisableAbstractElements.isSelected()) {
strings.put(DISABLE_ABSTRACT_ELEMENTS, Boolean.TRUE);
}
strings.put(ANY_PROCESS_CONTENTS, myAnyProcessContents.getSelectedItem());
strings.put(ANY_ATTRIBUTE_PROCESS_CONTENTS, myAnyAttributeProcessContents.getSelectedItem());
return strings;
}
public void setOptions(Map<String, ?> inputOptions) {
myDisableAbstractElements.setSelected(inputOptions.get(DISABLE_ABSTRACT_ELEMENTS) == Boolean.TRUE);
final Object o = inputOptions.get(ANY_PROCESS_CONTENTS);
if (o != null) {
myAnyProcessContents.setSelectedItem(o);
}
final Object o2 = inputOptions.get(ANY_ATTRIBUTE_PROCESS_CONTENTS);
if (o2 != null) {
myAnyAttributeProcessContents.setSelectedItem(o2);
}
}
}
@@ -0,0 +1,121 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.convert;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.xml.XmlDocument;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import org.intellij.plugins.relaxNG.ProjectLoader;
import org.intellij.plugins.relaxNG.compact.RncFileType;
import org.intellij.plugins.relaxNG.validation.ValidateAction;
import java.io.File;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 16.11.2007
*/
public class ConvertSchemaAction extends AnAction {
public void update(AnActionEvent e) {
final VirtualFile[] files = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY);
final Project project = e.getData(PlatformDataKeys.PROJECT);
if (files != null && project != null) {
final SchemaType type = getInputType(project, files);
e.getPresentation().setEnabled(type != null);
if (type == SchemaType.XML) {
e.getPresentation().setText("Generate Schema from XML file" + (files.length > 1 ? "s" : "") + "...");
} else {
e.getPresentation().setText("Convert Schema...");
}
} else {
e.getPresentation().setEnabled(false);
}
}
private static SchemaType getInputType(Project project, VirtualFile... files) {
if (files.length == 0) return null;
final VirtualFile file = files[0];
final FileType type = file.getFileType();
if (type == StdFileTypes.XML) {
final PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
if (psiFile instanceof XmlFile) {
final XmlDocument document = ((XmlFile)psiFile).getDocument();
if (document != null && document.getRootTag() != null) {
final XmlTag rootTag = document.getRootTag();
assert rootTag != null;
final String uri = rootTag.getNamespace();
if (ProjectLoader.RNG_NAMESPACE.equals(uri) && files.length == 1) {
return SchemaType.RNG;
}
}
}
if (files.length > 1) {
for (VirtualFile virtualFile : files) {
if (virtualFile.getFileType() != StdFileTypes.XML || getInputType(project, virtualFile) != null) {
return null;
}
}
}
return SchemaType.XML;
} else if (type == StdFileTypes.DTD && files.length == 1) {
return SchemaType.DTD;
} else if (type == RncFileType.getInstance() && files.length == 1) {
return SchemaType.RNC;
}
return null;
}
public void actionPerformed(AnActionEvent e) {
final VirtualFile file = e.getData(PlatformDataKeys.VIRTUAL_FILE);
final Project project = e.getData(PlatformDataKeys.PROJECT);
if (file != null && project != null) {
final VirtualFile[] files = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY);
assert files != null;
final SchemaType type = getInputType(project, files);
final ConvertSchemaDialog dialog = new ConvertSchemaDialog(project, type, file);
dialog.show();
if (!dialog.isOK()) {
return;
}
ValidateAction.saveFiles(files);
final ConvertSchemaSettings settings = dialog.getSettings();
final IdeaErrorHandler errorHandler = new IdeaErrorHandler(project);
new IdeaDriver(settings, project).convert(type, errorHandler, files);
final VirtualFile output = LocalFileSystem.getInstance().findFileByIoFile(new File(settings.getOutputDestination()));
if (output != null) {
output.refresh(false, true);
}
}
}
}
@@ -0,0 +1,86 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.convert;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 16.11.2007
*/
public class ConvertSchemaDialog extends DialogWrapper implements PropertyChangeListener {
private final ConvertSchemaSettingsImpl mySettings;
private final AbstractAction myAdvancedAction;
protected ConvertSchemaDialog(Project project, SchemaType input, VirtualFile firstFile) {
super(project, false);
setTitle("Convert Schema File");
mySettings = new ConvertSchemaSettingsImpl(project, input, firstFile);
mySettings.addPropertyChangeListener(ConvertSchemaSettingsImpl.OUTPUT_TYPE, this);
mySettings.addPropertyChangeListener(ConvertSchemaSettingsImpl.OUTPUT_PATH, this);
myAdvancedAction = new AbstractAction("Advanced...") {
public void actionPerformed(ActionEvent e) {
mySettings.showAdvancedSettings();
}
};
myAdvancedAction.setEnabled(mySettings.hasAdvancedSettings());
init();
getOKAction().setEnabled(mySettings.getOutputDestination().trim().length() > 0);
}
@Override
protected Action[] createLeftSideActions() {
return new Action[]{
myAdvancedAction
};
}
@Override
public JComponent getPreferredFocusedComponent() {
return mySettings.getPreferredFocusedComponent();
}
@Nullable
protected JComponent createCenterPanel() {
return mySettings.getRoot();
}
public ConvertSchemaSettings getSettings() {
return mySettings;
}
public void propertyChange(PropertyChangeEvent evt) {
if (ConvertSchemaSettingsImpl.OUTPUT_TYPE.equals(evt.getPropertyName())) {
myAdvancedAction.setEnabled(mySettings.hasAdvancedSettings());
} else if (ConvertSchemaSettingsImpl.OUTPUT_PATH.equals(evt.getPropertyName())) {
getOKAction().setEnabled(((String)evt.getNewValue()).trim().length() > 0);
}
}
}
@@ -0,0 +1,41 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.convert;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 17.11.2007
*/
public interface ConvertSchemaSettings {
@NotNull
SchemaType getOutputType();
String getOutputEncoding();
int getIndent();
int getLineLength();
String getOutputDestination();
void addAdvancedSettings(List<String> inputParams, List<String> outputParams);
}
@@ -0,0 +1,152 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.intellij.plugins.relaxNG.convert.ConvertSchemaSettingsImpl">
<grid id="27dc6" binding="myRoot" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="496" height="223"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<vspacer id="954f0">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<grid id="ba28d" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none" title="Output Type"/>
<children>
<component id="ae717" class="javax.swing.JRadioButton" binding="myOutputRnc">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="RELAX NG - &amp;Compact Syntax"/>
</properties>
</component>
<component id="42e64" class="javax.swing.JRadioButton" binding="myOutputXsd">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="W3C XML &amp;Schema"/>
</properties>
</component>
<component id="68cdd" class="javax.swing.JRadioButton" binding="myOutputDtd">
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&amp;DTD"/>
</properties>
</component>
<component id="a174f" class="javax.swing.JRadioButton" binding="myOutputRng">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&amp;RELAX NG - XML Syntax"/>
</properties>
</component>
</children>
</grid>
<grid id="a8d13" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none" title="Output Options"/>
<children>
<component id="a450" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="2ab32"/>
<text value="&amp;Encoding:"/>
</properties>
</component>
<vspacer id="deedc">
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="2ab32" class="com.intellij.openapi.ui.ComboBox" binding="myEncoding">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<component id="b3b11" class="javax.swing.JTextField" binding="myIndent">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="ce882" class="javax.swing.JLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="b3b11"/>
<text value="&amp;Indent:"/>
</properties>
</component>
<component id="42a61" class="javax.swing.JLabel">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="9a106"/>
<text value="&amp;Line Length:"/>
</properties>
</component>
<component id="9a106" class="javax.swing.JTextField" binding="myLineLength">
<constraints>
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
</children>
</grid>
<grid id="816e7" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="1" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none" title="Output Destination"/>
<children>
<component id="5b279" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myOutputDestination">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
</children>
</grid>
</children>
</grid>
<buttonGroups>
<group name="outputType">
<member id="ae717"/>
<member id="ae717"/>
<member id="42e64"/>
<member id="68cdd"/>
<member id="a174f"/>
</group>
</buttonGroups>
<inspectionSuppressions>
<suppress inspection="NoLabelFor" id="5b279"/>
</inspectionSuppressions>
</form>
@@ -0,0 +1,257 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.convert;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.encoding.EncodingManager;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.ui.DocumentAdapter;
import org.intellij.plugins.relaxNG.compact.RncFileType;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
import java.nio.charset.Charset;
import java.util.*;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 16.11.2007
*/
public class ConvertSchemaSettingsImpl implements ConvertSchemaSettings {
static final String OUTPUT_TYPE = "output-type";
static final String OUTPUT_PATH = "output-path";
private final PropertyChangeSupport myPropertyChangeSupport = new PropertyChangeSupport(this);
private final Project myProject;
private final SchemaType myInputType;
private Map<String, ?> myInputOptions = Collections.emptyMap();
private Map<String, ?> myOutputOptions = Collections.emptyMap();
private JPanel myRoot;
private JRadioButton myOutputRng;
private JRadioButton myOutputRnc;
private JRadioButton myOutputXsd;
private JRadioButton myOutputDtd;
private ComboBox myEncoding;
private JTextField myIndent;
private JTextField myLineLength;
private TextFieldWithBrowseButton myOutputDestination;
public ConvertSchemaSettingsImpl(Project project, @NotNull SchemaType inputType, VirtualFile firstFile) {
myProject = project;
myInputType = inputType;
final FileType type;
switch (inputType) {
case RNG:
myOutputRng.setVisible(false);
myOutputXsd.setSelected(true);
type = StdFileTypes.XML;
break;
case RNC:
myOutputRnc.setVisible(false);
myOutputRng.setSelected(true);
type = RncFileType.getInstance();
break;
case XSD:
myOutputXsd.setVisible(false);
myOutputRng.setSelected(true);
type = StdFileTypes.XML;
break;
case DTD:
myOutputDtd.setVisible(false);
myOutputRng.setSelected(true);
type = StdFileTypes.DTD;
break;
case XML:
myOutputRng.setSelected(true);
type = StdFileTypes.XML;
break;
default:
assert false;
type = null;
}
final Charset[] charsets = CharsetToolkit.getAvailableCharsets();
final List<String> suggestions = new ArrayList<String>(charsets.length);
for (Charset charset : charsets) {
if (charset.canEncode()) {
String name = charset.name();
suggestions.add(name);
}
}
myEncoding.setModel(new DefaultComboBoxModel(suggestions.toArray()));
final Charset charset = EncodingManager.getInstance().getDefaultCharset();
if (charset == null) {
myEncoding.setSelectedItem(System.getProperty("file.encoding", "UTF-8"));
} else {
myEncoding.setSelectedItem(charset.name());
}
final CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(project);
final int indent = styleSettings.getIndentSize(type);
myIndent.setText(String.valueOf(indent));
myLineLength.setText(String.valueOf(styleSettings.RIGHT_MARGIN));
final SchemaType outputType = getOutputType();
myLineLength.setEnabled(outputType == SchemaType.DTD || outputType == SchemaType.RNC);
final FileChooserDescriptor descriptor = new FileChooserDescriptor(true, true, false, false, false, false);
final Module module = ProjectRootManager.getInstance(project).getFileIndex().getModuleForFile(firstFile);
descriptor.putUserData(LangDataKeys.MODULE_CONTEXT, module);
myOutputDestination.addBrowseFolderListener("Schema Conversion Destination",
"Please select the destination the generated file(s) should be placed at", project, descriptor);
final JTextField tf = myOutputDestination.getTextField();
tf.getDocument().addDocumentListener(new DocumentAdapter() {
protected void textChanged(DocumentEvent e) {
myPropertyChangeSupport.firePropertyChange(OUTPUT_PATH, null, getOutputDestination());
}
});
tf.setText(firstFile.getParent().getPath().replace('/', File.separatorChar));
final ItemListener listener = new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
final SchemaType type = getOutputType();
myPropertyChangeSupport.firePropertyChange(OUTPUT_TYPE, null, type);
myLineLength.setEnabled(type == SchemaType.DTD || type == SchemaType.RNC);
}
}
};
myOutputRng.addItemListener(listener);
myOutputRnc.addItemListener(listener);
myOutputXsd.addItemListener(listener);
myOutputDtd.addItemListener(listener);
if (inputType == SchemaType.DTD) {
myInputOptions = AdvancedDtdOptions.prepareNamespaceMap(project, firstFile);
}
}
@NotNull
public SchemaType getOutputType() {
if (myOutputRng.isSelected()) {
return SchemaType.RNG;
} else if (myOutputRnc.isSelected()) {
return SchemaType.RNC;
} else if (myOutputXsd.isSelected()) {
return SchemaType.XSD;
} else {
assert myOutputDtd.isSelected();
return SchemaType.DTD;
}
}
public String getOutputEncoding() {
return (String)myEncoding.getSelectedItem();
}
public int getIndent() {
return parseInt(myIndent.getText().trim());
}
private static int parseInt(String s) {
try {
return s.length() > 0 ? Integer.parseInt(s) : -1;
} catch (NumberFormatException e) {
return -1;
}
}
public int getLineLength() {
return parseInt(myLineLength.getText());
}
public String getOutputDestination() {
return myOutputDestination.getText();
}
public void addAdvancedSettings(List<String> inputParams, List<String> outputParams) {
setParams(myInputOptions, inputParams);
if (getOutputType() == SchemaType.XSD) {
setParams(myOutputOptions, outputParams);
}
}
private static void setParams(Map<String, ?> map, List<String> inputParams) {
final Set<String> set = map.keySet();
for (String s : set) {
final Object value = map.get(s);
if (value == Boolean.TRUE) {
inputParams.add(s);
} else if (value == Boolean.FALSE) {
inputParams.add("no-" + s);
} else if (value != null) {
inputParams.add(s + "=" + value);
}
}
}
public JComponent getRoot() {
return myRoot;
}
public JComponent getPreferredFocusedComponent() {
return myOutputDestination;
}
public void addPropertyChangeListener(String name, PropertyChangeListener listener) {
myPropertyChangeSupport.addPropertyChangeListener(name, listener);
}
public void showAdvancedSettings() {
final AdvancedOptionsDialog dialog = new AdvancedOptionsDialog(myProject, myInputType, getOutputType());
dialog.setOptions(myInputOptions, myOutputOptions);
dialog.show();
if (dialog.isOK()) {
myInputOptions = dialog.getInputOptions();
myOutputOptions = dialog.getOutputOptions();
}
}
public boolean hasAdvancedSettings() {
return getOutputType() == SchemaType.XSD || myInputType == SchemaType.DTD;
}
}
@@ -0,0 +1,210 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.convert;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.VirtualFile;
import com.thaiopensource.relaxng.edit.SchemaCollection;
import com.thaiopensource.relaxng.input.InputFailedException;
import com.thaiopensource.relaxng.input.InputFormat;
import com.thaiopensource.relaxng.input.MultiInputFormat;
import com.thaiopensource.relaxng.input.dtd.DtdInputFormat;
import com.thaiopensource.relaxng.input.parse.compact.CompactParseInputFormat;
import com.thaiopensource.relaxng.input.parse.sax.SAXParseInputFormat;
import com.thaiopensource.relaxng.input.xml.XmlInputFormat;
import com.thaiopensource.relaxng.output.LocalOutputDirectory;
import com.thaiopensource.relaxng.output.OutputDirectory;
import com.thaiopensource.relaxng.output.OutputFailedException;
import com.thaiopensource.relaxng.output.OutputFormat;
import com.thaiopensource.relaxng.output.dtd.DtdOutputFormat;
import com.thaiopensource.relaxng.output.rnc.RncOutputFormat;
import com.thaiopensource.relaxng.output.rng.RngOutputFormat;
import com.thaiopensource.relaxng.output.xsd.XsdOutputFormat;
import com.thaiopensource.relaxng.translate.util.InvalidParamsException;
import com.thaiopensource.util.UriOrFile;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.charset.Charset;
import java.util.ArrayList;
public class IdeaDriver {
private static final int DEFAULT_LINE_LENGTH = 72;
private static final int DEFAULT_INDENT = 2;
private final ConvertSchemaSettings settings;
private final Project myProject;
public IdeaDriver(ConvertSchemaSettings settings, Project project) {
this.settings = settings;
myProject = project;
}
@SuppressWarnings({ "ThrowableInstanceNeverThrown" })
public void convert(SchemaType inputType, IdeaErrorHandler errorHandler, VirtualFile... inputFiles) {
if (inputFiles.length == 0) {
throw new IllegalArgumentException();
}
try {
final InputFormat inFormat = getInputFormat(inputType);
if (inputFiles.length > 1) {
if (!(inFormat instanceof MultiInputFormat)) {
throw new IllegalArgumentException();
}
}
final VirtualFile inputFile = inputFiles[0];
final SchemaType type = settings.getOutputType();
final String outputType = type.toString().toLowerCase();
final ArrayList<String> inputParams = new ArrayList<String>();
if (inputType != SchemaType.DTD) {
final Charset charset = inputFile.getCharset();
if (charset != null) {
inputParams.add("encoding=" + charset.name());
}
}
final ArrayList<String> outputParams = new ArrayList<String>();
settings.addAdvancedSettings(inputParams, outputParams);
// System.out.println("INPUT: " + inputParams);
// System.out.println("OUTPUT: " + outputParams);
final SchemaCollection sc;
final String input = inputFile.getPath();
final String uri = UriOrFile.toUri(input);
try {
if (inFormat instanceof MultiInputFormat) {
final MultiInputFormat format = (MultiInputFormat)inFormat;
final String[] uris = new String[inputFiles.length];
for (int i = 0; i < inputFiles.length; i++) {
uris[i] = UriOrFile.toUri(inputFiles[i].getPath());
}
sc = format.load(uris, inputParams.toArray(new String[inputParams.size()]), outputType, errorHandler);
} else {
sc = inFormat.load(uri, inputParams.toArray(new String[inputParams.size()]), outputType, errorHandler);
}
} catch (IOException e) {
errorHandler.fatalError(new SAXParseException(e.getMessage(), null, uri, -1, -1, e));
return;
}
final File destination = new File(settings.getOutputDestination());
final File outputFile;
if (destination.isDirectory()) {
final String name = new File(input).getName();
final int ext = name.lastIndexOf('.');
outputFile = new File(destination, (ext > 0 ? name.substring(0, ext) : name) + "." + outputType);
} else {
outputFile = destination;
}
try {
final int indent = settings.getIndent();
final int length = settings.getLineLength();
final OutputDirectory od = new LocalOutputDirectory(sc.getMainUri(),
outputFile,
"." + outputType,
settings.getOutputEncoding(),
length > 0 ? length : DEFAULT_LINE_LENGTH,
indent > 0 ? indent : DEFAULT_INDENT)
{
public Stream open(String sourceUri, String encoding) throws IOException {
final String s = super.reference(null, sourceUri);
final File file = new File(outputFile.getParentFile(), s);
if (file.exists()) {
final String msg = "The file '" + file.getAbsolutePath() + "' already exists. Overwrite it?";
final int choice = Messages.showYesNoDialog(myProject, msg, "Output File Exists", Messages.getWarningIcon());
if (choice == 0) {
return super.open(sourceUri, encoding);
} else if (choice == 1) {
throw new CanceledException();
}
}
return super.open(sourceUri, encoding);
}
};
final OutputFormat of = getOutputFormat(settings.getOutputType());
of.output(sc, od, outputParams.toArray(new String[outputParams.size()]), inputType.toString().toLowerCase(), errorHandler);
} catch (IOException e) {
errorHandler.fatalError(new SAXParseException(e.getMessage(), null, UriOrFile.fileToUri(outputFile), -1, -1, e));
}
} catch (CanceledException e) {
// user abort
} catch (SAXParseException e) {
errorHandler.error(e);
} catch (MalformedURLException e) {
Logger.getInstance(getClass().getName()).error(e);
} catch (InputFailedException e) {
// handled by ErrorHandler
} catch (InvalidParamsException e) {
// handled by ErrorHandler
} catch (OutputFailedException e) {
// handled by ErrorHandler
} catch (SAXException e) {
// cannot happen or is already handled
}
}
private OutputFormat getOutputFormat(SchemaType outputType) {
switch (outputType) {
case DTD:
return new DtdOutputFormat();
case RNC:
return new RncOutputFormat();
case RNG:
return new RngOutputFormat();
case XSD:
return new XsdOutputFormat();
default:
assert false : "Unsupported output type: " + outputType;
return null;
}
}
private InputFormat getInputFormat(SchemaType type) {
switch (type) {
case DTD:
return new DtdInputFormat();
case RNC:
return new CompactParseInputFormat();
case RNG:
return new SAXParseInputFormat();
case XML:
return new XmlInputFormat();
default:
assert false : "Unsupported input type: " + type;
return null;
}
}
private static class CanceledException extends RuntimeException {
}
}
@@ -0,0 +1,57 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.convert;
import org.intellij.plugins.relaxNG.validation.MessageViewHelper;
import com.intellij.ide.errorTreeView.NewErrorTreeViewPanel;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.thaiopensource.xml.sax.ErrorHandlerImpl;
import org.xml.sax.SAXParseException;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 16.11.2007
*/
public class IdeaErrorHandler extends ErrorHandlerImpl {
private static final String CONTENT_NAME = "Convert Schema";
private static final Key<NewErrorTreeViewPanel> KEY = Key.create("CONVERSION_ERRORS");
private final MessageViewHelper myMessageViewHelper;
public IdeaErrorHandler(Project project) {
myMessageViewHelper = new MessageViewHelper(project, CONTENT_NAME, KEY);
}
@Override
public void warning(SAXParseException e) throws SAXParseException {
myMessageViewHelper.processError(e, true);
}
@Override
public void error(SAXParseException e) {
myMessageViewHelper.processError(e, false);
}
@Override
public void fatalError(SAXParseException e) throws SAXParseException {
myMessageViewHelper.processError(e, false);
}
}
@@ -0,0 +1,28 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.convert;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 17.11.2007
*/
public enum SchemaType {
RNG, RNC, DTD,
XSD, // output only
XML // input only
}
@@ -0,0 +1,220 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.inspections;
import org.intellij.plugins.relaxNG.compact.psi.*;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.codeInspection.SuppressIntentionAction;
import com.intellij.codeInspection.XmlSuppressableInspectionTool;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.ReadonlyStatusHandler;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 25.11.2007
*/
public abstract class BaseInspection extends XmlSuppressableInspectionTool {
@Nls
@NotNull
public final String getGroupDisplayName() {
return getRngGroupDisplayName();
}
public static String getRngGroupDisplayName() {
return "RELAX NG";
}
@SuppressWarnings({ "SSBasedInspection" })
@Override
public boolean isSuppressedFor(PsiElement element) {
if (element.getContainingFile() instanceof RncFile) {
final RncDefine define = PsiTreeUtil.getParentOfType(element, RncDefine.class, false);
if (define != null) {
if (isSuppressedAt(define)) return true;
}
final RncGrammar grammar = PsiTreeUtil.getParentOfType(define, RncGrammar.class);
if (grammar != null) {
if (isSuppressedAt(grammar)) return true;
}
return false;
} else {
return super.isSuppressedFor(element);
}
}
@SuppressWarnings({ "SSBasedInspection" })
private boolean isSuppressedAt(RncElement location) {
PsiElement prev = location.getPrevSibling();
while (prev instanceof PsiWhiteSpace || prev instanceof PsiComment) {
if (prev instanceof PsiComment) {
@NonNls String text = prev.getText();
if (text.matches("\n*#\\s*suppress\\s.+") && (text.contains(getID()) || "ALL".equals(text))) return true;
}
prev = prev.getPrevSibling();
}
return false;
}
@Override
@Nullable
public SuppressIntentionAction[] getSuppressActions(PsiElement element) {
if (element.getContainingFile() instanceof RncFile) {
return ArrayUtil.mergeArrays(new SuppressIntentionAction[]{
new SuppressAction("Define") {
protected PsiElement getTarget(PsiElement element) {
return PsiTreeUtil.getParentOfType(element, RncDefine.class, false);
}
},
new SuppressAction("Grammar") {
protected PsiElement getTarget(PsiElement element) {
final RncDefine define = PsiTreeUtil.getParentOfType(element, RncDefine.class, false);
return define != null ? PsiTreeUtil.getParentOfType(define, RncGrammar.class, false) : null;
}
@SuppressWarnings({ "SSBasedInspection" })
public boolean isAvailable(@NotNull Project project, Editor editor, @Nullable PsiElement element) {
return super.isAvailable(project, editor, element) && getTarget(element).getText().startsWith("grammar ");
}
}
}, getXmlOnlySuppressions(element), SuppressIntentionAction.class);
} else {
return super.getSuppressActions(element);
}
}
private SuppressIntentionAction[] getXmlOnlySuppressions(PsiElement element) {
return ContainerUtil.map(super.getSuppressActions(element), new Function<SuppressIntentionAction, SuppressIntentionAction>() {
public SuppressIntentionAction fun(final SuppressIntentionAction action) {
return new SuppressIntentionAction() {
public void invoke(Project project, Editor editor, PsiElement element) throws IncorrectOperationException {
action.invoke(project, editor, element);
}
public boolean isAvailable(@NotNull Project project, Editor editor, @Nullable PsiElement element) {
return element != null && element.getContainingFile().getFileType() == StdFileTypes.XML &&
action.isAvailable(project, editor, element);
}
@NotNull
public String getText() {
return action.getText();
}
public boolean startInWriteAction() {
return action.startInWriteAction();
}
@NotNull
public String getFamilyName() {
return action.getFamilyName();
}
};
}
}, new SuppressIntentionAction[0]);
}
private void suppress(PsiFile file, @NotNull PsiElement location) {
suppress(file, location, "#suppress " + getID(), new Function<String, String>() {
public String fun(final String text) {
return text + ", " + getID();
}
});
}
@SuppressWarnings({ "SSBasedInspection" })
private static void suppress(PsiFile file, @NotNull PsiElement location, String suppressComment, Function<String, String> replace) {
final Project project = file.getProject();
final VirtualFile vfile = file.getVirtualFile();
if (vfile == null || ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(vfile).hasReadonlyFiles()) {
return;
}
final Document doc = PsiDocumentManager.getInstance(project).getDocument(file);
assert doc != null;
PsiElement leaf = location.getPrevSibling();
while (leaf instanceof PsiWhiteSpace) leaf = leaf.getPrevSibling();
while (leaf instanceof PsiComment || leaf instanceof PsiWhiteSpace) {
@NonNls String text = leaf.getText();
if (text.matches("\n*#\\s*suppress\\s.+")) {
final TextRange textRange = leaf.getTextRange();
doc.replaceString(textRange.getStartOffset(), textRange.getEndOffset(), replace.fun(text));
return;
}
leaf = leaf.getPrevSibling();
}
final int offset = location.getTextRange().getStartOffset();
doc.insertString(offset, suppressComment + "\n");
CodeStyleManager.getInstance(project).adjustLineIndent(doc, offset + suppressComment.length());
// UndoManager.getInstance(file.getProject()).markDocumentForUndo(file);
}
@Override
@NotNull
public abstract RncElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly);
private abstract class SuppressAction extends SuppressIntentionAction {
private final String myLocation;
public SuppressAction(String location) {
myLocation = location;
}
@NotNull
public String getText() {
return "Suppress for " + myLocation;
}
@NotNull
public String getFamilyName() {
return getDisplayName();
}
public void invoke(Project project, Editor editor, PsiElement element) throws IncorrectOperationException {
suppress(element.getContainingFile(), getTarget(element));
}
public boolean isAvailable(@NotNull Project project, Editor editor, @Nullable PsiElement element) {
return getTarget(element) != null;
}
protected abstract PsiElement getTarget(PsiElement element);
}
}
@@ -0,0 +1,65 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.inspections;
import org.intellij.plugins.relaxNG.xml.dom.RngDomElement;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.util.xml.highlighting.BasicDomElementsInspection;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 03.10.2007
*/
public class RngDomInspection extends BasicDomElementsInspection<RngDomElement> {
public RngDomInspection() {
super(RngDomElement.class);
}
@NotNull
@Override
public HighlightDisplayLevel getDefaultLevel() {
return HighlightDisplayLevel.ERROR;
}
@Override
public boolean isEnabledByDefault() {
return true;
}
@Nls
@NotNull
public String getGroupDisplayName() {
return BaseInspection.getRngGroupDisplayName();
}
@Nls
@NotNull
public String getDisplayName() {
return "Unresolved References";
}
@NonNls
@NotNull
public String getShortName() {
return "UnresolvedReference";
}
}
@@ -0,0 +1,230 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.inspections;
import org.intellij.plugins.relaxNG.ProjectLoader;
import org.intellij.plugins.relaxNG.compact.psi.RncDefine;
import org.intellij.plugins.relaxNG.compact.psi.RncElementVisitor;
import org.intellij.plugins.relaxNG.compact.psi.RncGrammar;
import org.intellij.plugins.relaxNG.compact.psi.impl.RncDefineImpl;
import org.intellij.plugins.relaxNG.model.resolve.RelaxIncludeIndex;
import org.intellij.plugins.relaxNG.xml.dom.RngGrammar;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference;
import com.intellij.psi.XmlElementVisitor;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Query;
import com.intellij.util.xml.DomElement;
import com.intellij.util.xml.DomManager;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 26.07.2007
*/
public class UnusedDefineInspection extends BaseInspection {
public boolean isEnabledByDefault() {
return false;
}
@Nls
@NotNull
public String getDisplayName() {
return "Unused Define";
}
@NonNls
@NotNull
public String getShortName() {
return "UnusedDefine";
}
@NotNull
public RncElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
return new MyElementVisitor(holder);
}
private static final class MyElementVisitor extends RncElementVisitor {
private final ProblemsHolder myHolder;
private final XmlElementVisitor myXmlVisitor = new XmlElementVisitor() {
@Override
public void visitXmlTag(XmlTag tag) {
MyElementVisitor.this.visitXmlTag(tag);
}
};
public MyElementVisitor(ProblemsHolder holder) {
myHolder = holder;
}
protected void superVisitElement(PsiElement element) {
element.accept(myXmlVisitor);
}
@Override
public void visitDefine(RncDefine pattern) {
final RncGrammar grammar = PsiTreeUtil.getParentOfType(pattern, RncGrammar.class);
final PsiFile file = pattern.getContainingFile();
if (grammar != null) {
if (processRncUsages(pattern, new LocalSearchScope(grammar))) return;
} else {
if (processRncUsages(pattern, new LocalSearchScope(file))) return;
}
final PsiElementProcessor.CollectElements<XmlFile> collector = new PsiElementProcessor.CollectElements<XmlFile>();
RelaxIncludeIndex.processBackwardDependencies((XmlFile)file, collector);
if (processRncUsages(pattern, new LocalSearchScope(collector.toArray()))) return;
final ASTNode astNode = ((RncDefineImpl)pattern).getNameNode();
myHolder.registerProblem(astNode.getPsi(), "Unreferenced define", ProblemHighlightType.LIKE_UNUSED_SYMBOL, new MyFix<RncDefine>(pattern));
}
private static boolean processRncUsages(PsiElement tag, LocalSearchScope scope) {
final Query<PsiReference> query = ReferencesSearch.search(tag, scope);
for (PsiReference reference : query) {
final PsiElement e = reference.getElement();
final RncDefine t = PsiTreeUtil.getParentOfType(e, RncDefine.class, false);
if (t == null || !PsiTreeUtil.isAncestor(tag, t, true)) {
return true;
}
}
return false;
}
public void visitXmlTag(XmlTag tag) {
final PsiFile file = tag.getContainingFile();
if (file.getFileType() != StdFileTypes.XML) {
return;
}
if (!tag.getLocalName().equals("define")) {
return;
}
if (!tag.getNamespace().equals(ProjectLoader.RNG_NAMESPACE)) {
return;
}
if (tag.getAttribute("combine") != null) {
return; // ?
}
final XmlAttribute attr = tag.getAttribute("name");
if (attr == null) return;
final XmlAttributeValue value = attr.getValueElement();
if (value == null) return;
final String s = value.getValue();
if (s == null || s.length() == 0) {
return;
}
final PsiElement parent = value.getParent();
if (!(parent instanceof XmlAttribute)) {
return;
}
if (!"name".equals(((XmlAttribute)parent).getName())) {
return;
}
final PsiElement grandParent = parent.getParent();
if (!(grandParent instanceof XmlTag)) {
return;
}
final DomElement element = DomManager.getDomManager(tag.getProject()).getDomElement(tag);
if (element == null) {
return;
}
final RngGrammar rngGrammar = element.getParentOfType(RngGrammar.class, true);
if (rngGrammar != null) {
if (processUsages(tag, value, new LocalSearchScope(rngGrammar.getXmlTag()))) return;
} else {
if (processUsages(tag, value, new LocalSearchScope(file))) return;
}
final PsiElementProcessor.CollectElements<XmlFile> collector = new PsiElementProcessor.CollectElements<XmlFile>();
RelaxIncludeIndex.processBackwardDependencies((XmlFile)file, collector);
if (processUsages(tag, value, new LocalSearchScope(collector.toArray()))) return;
myHolder.registerProblem(value, "Unreferenced define", ProblemHighlightType.LIKE_UNUSED_SYMBOL, new MyFix<XmlTag>(tag));
}
private static boolean processUsages(PsiElement tag, XmlAttributeValue value, LocalSearchScope scope) {
final Query<PsiReference> query = ReferencesSearch.search(tag, scope, true);
for (PsiReference reference : query) {
final PsiElement e = reference.getElement();
if (e != value) {
final XmlTag t = PsiTreeUtil.getParentOfType(e, XmlTag.class);
if (t != null && !PsiTreeUtil.isAncestor(tag, t, true)) {
return true;
}
}
}
return false;
}
private static class MyFix<T extends PsiElement> implements LocalQuickFix {
private final T myTag;
public MyFix(T tag) {
myTag = tag;
}
@NotNull
public String getName() {
return "Remove Define";
}
@NotNull
public String getFamilyName() {
return getName();
}
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
try {
if (myTag.isValid()) {
myTag.delete();
}
} catch (IncorrectOperationException e) {
Logger.getInstance(UnusedDefineInspection.class.getName()).error(e);
}
}
}
}
}
@@ -0,0 +1,63 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.model;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 17.09.2007
*/
public interface CommonElement<E extends PsiElement> {
void accept(Visitor visitor);
void acceptChildren(Visitor visitor);
@Nullable
E getPsiElement();
static abstract class Visitor {
public void visitElement(CommonElement pattern) {
}
public void visitPattern(Pattern pattern) {
visitElement(pattern);
}
public void visitGrammar(Grammar pattern) {
visitElement(pattern);
}
public void visitDefine(Define define) {
visitElement(define);
}
public void visitRef(Ref ref) {
visitElement(ref);
}
public void visitDiv(Div div) {
visitElement(div);
}
public void visitInclude(Include inc) {
visitElement(inc);
}
}
}
@@ -0,0 +1,34 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.model;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 05.09.2007
*/
public interface Define<P extends Pattern, E extends PsiElement> extends Pattern<E> {
String getName();
PsiElement getNameElement();
@Nullable
P getPattern();
}
@@ -0,0 +1,27 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.model;
import com.intellij.psi.PsiElement;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 17.09.2007
*/
public interface Div<E extends PsiElement> extends CommonElement<E> {
}
@@ -0,0 +1,28 @@
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.model;
import com.intellij.psi.PsiElement;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 24.08.2007
*/
public interface Grammar<P extends Pattern, E extends PsiElement> extends Pattern<E> {
P getStart();
}

Some files were not shown because too many files have changed in this diff Show More