Module descriptions in XML

This commit is contained in:
Andrey Breslav
2013-04-26 20:21:21 +04:00
parent 3673f8003b
commit 42505246b8
25 changed files with 833 additions and 2 deletions
@@ -0,0 +1,114 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.cli.common.modules;
import org.jetbrains.annotations.NotNull;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import java.io.IOException;
public abstract class DelegatedSaxHandler extends DefaultHandler {
@NotNull
protected abstract DefaultHandler getDelegate();
@Override
public InputSource resolveEntity(String publicId, String systemId) throws IOException, SAXException {
return getDelegate().resolveEntity(publicId, systemId);
}
@Override
public void notationDecl(String name, String publicId, String systemId) throws SAXException {
getDelegate().notationDecl(name, publicId, systemId);
}
@Override
public void unparsedEntityDecl(String name, String publicId, String systemId, String notationName) throws SAXException {
getDelegate().unparsedEntityDecl(name, publicId, systemId, notationName);
}
@Override
public void setDocumentLocator(Locator locator) {
getDelegate().setDocumentLocator(locator);
}
@Override
public void startDocument() throws SAXException {
getDelegate().startDocument();
}
@Override
public void endDocument() throws SAXException {
getDelegate().endDocument();
}
@Override
public void startPrefixMapping(String prefix, String uri) throws SAXException {
getDelegate().startPrefixMapping(prefix, uri);
}
@Override
public void endPrefixMapping(String prefix) throws SAXException {
getDelegate().endPrefixMapping(prefix);
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
getDelegate().startElement(uri, localName, qName, attributes);
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
getDelegate().endElement(uri, localName, qName);
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
getDelegate().characters(ch, start, length);
}
@Override
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
getDelegate().ignorableWhitespace(ch, start, length);
}
@Override
public void processingInstruction(String target, String data) throws SAXException {
getDelegate().processingInstruction(target, data);
}
@Override
public void skippedEntity(String name) throws SAXException {
getDelegate().skippedEntity(name);
}
@Override
public void warning(SAXParseException e) throws SAXException {
getDelegate().warning(e);
}
@Override
public void error(SAXParseException e) throws SAXException {
getDelegate().error(e);
}
@Override
public void fatalError(SAXParseException e) throws SAXException {
getDelegate().fatalError(e);
}
}
@@ -0,0 +1,93 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.cli.common.modules;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* This interface duplicates {@link jet.modules.Module}, because cli-common should not depend on kotlin-runtime.jar
*/
public interface ModuleDescription {
@NotNull
String getModuleName();
@NotNull
List<String> getSourceFiles();
@NotNull
List<String> getClasspathRoots();
@NotNull
List<String> getAnnotationsRoots();
class Impl implements ModuleDescription {
private String name;
private final List<String> sources = new SmartList<String>();
private final List<String> classpath = new SmartList<String>();
private final List<String> annotations = new SmartList<String>();
public void setName(String name) {
this.name = name;
}
public void addSourcePath(String path) {
sources.add(path);
}
public void addClassPath(String path) {
classpath.add(path);
}
public void addAnnotationPath(String path) {
annotations.add(path);
}
@NotNull
@Override
public String getModuleName() {
return name;
}
@NotNull
@Override
public List<String> getSourceFiles() {
return sources;
}
@NotNull
@Override
public List<String> getClasspathRoots() {
return classpath;
}
@NotNull
@Override
public List<String> getAnnotationsRoots() {
return annotations;
}
@Override
public String toString() {
return name + "\n\tsources=" + sources + "\n\tclasspath=" + classpath + "\n\tannotations=" + annotations;
}
}
}
@@ -0,0 +1,178 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.cli.common.modules;
import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.cli.common.messages.*;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.*;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.jet.cli.common.messages.CompilerMessageLocation.*;
import static org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity.*;
public class ModuleXmlParser {
public static final String MODULES = "modules";
public static final String MODULE = "module";
public static final String NAME = "name";
public static final String SOURCES = "sources";
public static final String PATH = "path";
public static final String CLASSPATH = "classpath";
public static final String EXTERNAL_ANNOTATIONS = "externalAnnotations";
@NotNull
public static List<ModuleDescription> parse(@NotNull String xmlFile, @NotNull MessageCollector messageCollector) {
FileInputStream stream = null;
try {
stream = new FileInputStream(xmlFile);
//noinspection IOResourceOpenedButNotSafelyClosed
return new ModuleXmlParser(messageCollector).parse(new BufferedInputStream(stream));
}
catch (FileNotFoundException e) {
MessageCollectorUtil.reportException(messageCollector, e);
return Collections.emptyList();
}
finally {
StreamUtil.closeStream(stream);
}
}
private final MessageCollector messageCollector;
private final List<ModuleDescription> result = new SmartList<ModuleDescription>();
private DefaultHandler currentState;
private ModuleXmlParser(@NotNull MessageCollector messageCollector) {
this.messageCollector = messageCollector;
}
private void setCurrentState(@NotNull DefaultHandler currentState) {
this.currentState = currentState;
}
private List<ModuleDescription> parse(@NotNull InputStream xml) {
try {
setCurrentState(initial);
SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
saxParser.parse(xml, new DelegatedSaxHandler() {
@NotNull
@Override
protected DefaultHandler getDelegate() {
return currentState;
}
});
return result;
}
catch (ParserConfigurationException e) {
MessageCollectorUtil.reportException(messageCollector, e);
}
catch (SAXException e) {
messageCollector.report(ERROR, MessageRenderer.PLAIN.renderException(e), NO_LOCATION);
}
catch (IOException e) {
MessageCollectorUtil.reportException(messageCollector, e);
}
return Collections.emptyList();
}
private final DefaultHandler initial = new DefaultHandler() {
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (!MODULES.equalsIgnoreCase(qName)) {
throw createError(qName);
}
setCurrentState(insideModules);
}
};
private final DefaultHandler insideModules = new DefaultHandler() {
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (!MODULE.equalsIgnoreCase(qName)) {
throw createError(qName);
}
setCurrentState(new InsideModule(getAttribute(attributes, NAME, qName)));
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (MODULE.equalsIgnoreCase(qName) || MODULES.equalsIgnoreCase(qName)) {
setCurrentState(insideModules);
}
}
};
private class InsideModule extends DefaultHandler {
private final ModuleDescription.Impl moduleDescription;
private InsideModule(String name) {
this.moduleDescription = new ModuleDescription.Impl();
this.moduleDescription.setName(name);
result.add(moduleDescription);
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (SOURCES.equalsIgnoreCase(qName)) {
String path = getAttribute(attributes, PATH, qName);
moduleDescription.addSourcePath(path);
}
else if (CLASSPATH.equalsIgnoreCase(qName)) {
String path = getAttribute(attributes, PATH, qName);
moduleDescription.addClassPath(path);
}
else if (EXTERNAL_ANNOTATIONS.equalsIgnoreCase(qName)) {
String path = getAttribute(attributes, PATH, qName);
moduleDescription.addAnnotationPath(path);
}
else {
throw createError(qName);
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (MODULE.equalsIgnoreCase(qName)) {
setCurrentState(insideModules);
}
}
}
@NotNull
private static String getAttribute(Attributes attributes, String qName, String tag) throws SAXException {
String name = attributes.getValue(qName);
if (name == null) {
throw new SAXException("No '" + qName + "' attribute for " + tag);
}
return name;
}
private static SAXException createError(String qName) throws SAXException {
return new SAXException("Unexpected tag: " + qName);
}
}