blob: 0637de1f79d202af92fbc3bad4a910acf68ead27 [file] [log] [blame]
package org.intellij.plugins.relaxNG.model.resolve;
import com.intellij.ide.highlighter.XmlFileType;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.impl.include.FileIncludeInfo;
import com.intellij.psi.impl.include.FileIncludeProvider;
import com.intellij.util.Consumer;
import com.intellij.util.indexing.FileContent;
import com.intellij.util.text.CharArrayUtil;
import com.intellij.util.xml.NanoXmlUtil;
import org.intellij.plugins.relaxNG.ApplicationLoader;
import org.intellij.plugins.relaxNG.compact.RncFileType;
import org.intellij.plugins.relaxNG.compact.psi.RncElement;
import org.intellij.plugins.relaxNG.compact.psi.RncElementVisitor;
import org.intellij.plugins.relaxNG.compact.psi.RncInclude;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 09.06.2010
*/
public class RelaxIncludeProvider extends FileIncludeProvider {
@NotNull
@Override
public String getId() {
return "relax-ng";
}
@Override
public boolean acceptFile(VirtualFile file) {
final FileType type = file.getFileType();
return type == XmlFileType.INSTANCE || type == RncFileType.getInstance();
}
@Override
public void registerFileTypesUsedForIndexing(@NotNull Consumer<FileType> fileTypeSink) {
fileTypeSink.consume(XmlFileType.INSTANCE);
fileTypeSink.consume(RncFileType.getInstance());
}
@NotNull
@Override
public FileIncludeInfo[] getIncludeInfos(FileContent content) {
final ArrayList<FileIncludeInfo> infos;
if (content.getFileType() == XmlFileType.INSTANCE) {
CharSequence inputDataContentAsText = content.getContentAsText();
if (CharArrayUtil.indexOf(inputDataContentAsText, ApplicationLoader.RNG_NAMESPACE, 0) == -1) return FileIncludeInfo.EMPTY;
infos = new ArrayList<FileIncludeInfo>();
NanoXmlUtil.parse(CharArrayUtil.readerFromCharSequence(content.getContentAsText()), new RngBuilderAdapter(infos));
} else if (content.getFileType() == RncFileType.getInstance()) {
infos = new ArrayList<FileIncludeInfo>();
content.getPsiFile().acceptChildren(new RncElementVisitor() {
@Override
public void visitElement(RncElement element) {
element.acceptChildren(this);
}
@Override
public void visitInclude(RncInclude include) {
final String path = include.getFileReference();
if (path != null) {
infos.add(new FileIncludeInfo(path));
}
}
});
} else {
return FileIncludeInfo.EMPTY;
}
return infos.toArray(new FileIncludeInfo[infos.size()]);
}
private static class RngBuilderAdapter extends NanoXmlUtil.IXMLBuilderAdapter {
boolean isRNG;
boolean isInclude;
private final ArrayList<FileIncludeInfo> myInfos;
public RngBuilderAdapter(ArrayList<FileIncludeInfo> infos) {
myInfos = infos;
}
@Override
public void startElement(String name, String nsPrefix, String nsURI, String systemID, int lineNr) throws Exception {
boolean isRngTag = ApplicationLoader.RNG_NAMESPACE.equals(nsURI);
if (!isRNG) { // analyzing start tag
if (!isRngTag) {
stop();
} else {
isRNG = true;
}
}
isInclude = isRngTag && "include".equals(name);
}
@Override
public void addAttribute(String key, String nsPrefix, String nsURI, String value, String type) throws Exception {
if (isInclude && "href".equals(key)) {
myInfos.add(new FileIncludeInfo(value));
}
}
@Override
public void endElement(String name, String nsPrefix, String nsURI) throws Exception {
isInclude = false;
}
}
}