support modules & PsiReferenceProviderBean. And fix missing Action/Group methods.

This commit is contained in:
Gregory Shrago
2010-07-24 07:14:38 +04:00
parent 133e585579
commit 7a5ed76cc0
7 changed files with 127 additions and 37 deletions
+5 -2
View File
@@ -142,6 +142,9 @@ public interface Action extends DomElement {
*/
AddToGroup addAddToGroup();
@NotNull
GenericAttributeValue<String> getUseShortcutOf();
@NotNull
GenericAttributeValue<String> getUseShortcutOf();
@NotNull
GenericAttributeValue<String> getKeymap();
}
+2
View File
@@ -39,4 +39,6 @@ public interface Actions extends DomElement {
@NotNull
List<Reference> getReferences();
Reference addReference();
}
+1 -1
View File
@@ -28,7 +28,7 @@ import java.util.List;
/**
* plugin.dtd:group interface.
*/
public interface Group extends DomElement {
public interface Group extends Actions {
/**
* Returns the value of the popup child.
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.containers.ContainerUtil;
@@ -27,7 +28,10 @@ import com.intellij.util.xml.*;
import com.intellij.util.xml.reflect.DomExtender;
import com.intellij.util.xml.reflect.DomExtension;
import com.intellij.util.xml.reflect.DomExtensionsRegistrar;
import com.intellij.util.xmlb.Constants;
import com.intellij.util.xmlb.annotations.AbstractCollection;
import com.intellij.util.xmlb.annotations.Attribute;
import com.intellij.util.xmlb.annotations.Property;
import com.intellij.util.xmlb.annotations.Tag;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -65,7 +69,8 @@ public class ExtensionDomExtender extends DomExtender<Extensions> {
final Collection<String> dependencies = getDependencies(ideaPlugin);
for (IdeaPlugin plugin : IdeaPluginConverter.collectAllVisiblePlugins(DomUtil.getFile(extensions))) {
final String value = plugin.getPluginId();
if (value != null && dependencies.contains(value)) {
// value == null for "included" platform plugins like DomPlugin.xml, XmlPlugin.xml, etc.
if (value == null || dependencies.contains(value)) {
registerExtensions(prefix, plugin, registrar, psiManager);
}
}
@@ -74,7 +79,7 @@ public class ExtensionDomExtender extends DomExtender<Extensions> {
private static void registerExtensions(final String prefix, final IdeaPlugin plugin, final DomExtensionsRegistrar registrar,
final PsiManager psiManager) {
final String pluginId = plugin.getPluginId();
final String pluginId = StringUtil.notNullize(plugin.getPluginId(), "com.intellij");
for (ExtensionPoints points : plugin.getExtensionPoints()) {
for (ExtensionPoint point : points.getExtensionPoints()) {
registerExtensionPoint(registrar, point, psiManager, prefix, pluginId);
@@ -129,36 +134,109 @@ public class ExtensionDomExtender extends DomExtender<Extensions> {
}
private static void registerField(final DomExtensionsRegistrar registrar, @NotNull final PsiField field) {
final PsiAnnotation[] annotations = field.getModifierList().getAnnotations();
final PsiModifierList modifierList = field.getModifierList();
if (modifierList == null) return;
final PsiConstantEvaluationHelper evalHelper = JavaPsiFacade.getInstance(field.getProject()).getConstantEvaluationHelper();
for (PsiAnnotation annotation : annotations) {
final String qName = annotation.getQualifiedName();
if (qName != null) {
if (qName.equals(Attribute.class.getName())) {
final PsiAnnotationMemberValue attributeName = annotation.findAttributeValue("value");
if (attributeName != null && attributeName instanceof PsiExpression) {
final Class<String> type = String.class;
PsiExpression expression = (PsiExpression)attributeName;
final Object evaluatedExpression = evalHelper.computeConstantExpression(expression, false);
if (evaluatedExpression != null) {
registrar.registerGenericAttributeValueChildExtension(new XmlName(evaluatedExpression.toString()), type);
}
}
} else if (qName.equals(Tag.class.getName())) {
final PsiAnnotationMemberValue attributeName = annotation.findAttributeValue("value");
if (attributeName != null && attributeName instanceof PsiExpression) {
PsiExpression expression = (PsiExpression)attributeName;
final Object evaluatedExpression = evalHelper.computeConstantExpression(expression, false);
if (evaluatedExpression != null) {
// I guess this actually needs something like registrar.registerGenericTagValueChildExtension...
registrar.registerFixedNumberChildExtension(new XmlName(evaluatedExpression.toString()), SimpleTagValue.class);
}
}
final PsiAnnotation attrAnno = modifierList.findAnnotation(Attribute.class.getName());
if (attrAnno != null) {
final PsiAnnotationMemberValue attributeName = attrAnno.findAttributeValue("value");
if (attributeName != null && attributeName instanceof PsiExpression) {
final Class<String> type = String.class;
PsiExpression expression = (PsiExpression)attributeName;
final Object evaluatedExpression = evalHelper.computeConstantExpression(expression, false);
if (evaluatedExpression != null) {
registrar.registerGenericAttributeValueChildExtension(new XmlName(evaluatedExpression.toString()), type);
}
}
return;
}
final PsiAnnotation tagAnno = modifierList.findAnnotation(Tag.class.getName());
final PsiAnnotation propAnno = modifierList.findAnnotation(Property.class.getName());
final PsiAnnotation absColAnno = modifierList.findAnnotation(AbstractCollection.class.getName());
//final PsiAnnotation colAnno = modifierList.findAnnotation(Collection.class.getName()); // todo
final String tagName = tagAnno != null? getStringAttribute(tagAnno, "value", evalHelper) :
propAnno != null && getBooleanAttribute(propAnno, "surroundWithTag", evalHelper)? Constants.OPTION : null;
if (tagName != null) {
if (absColAnno == null) {
registrar.registerFixedNumberChildExtension(new XmlName(tagName), SimpleTagValue.class);
}
else {
registrar.registerFixedNumberChildExtension(new XmlName(tagName), DomElement.class).addExtender(new DomExtender() {
@Override
public void registerExtensions(@NotNull DomElement domElement, @NotNull DomExtensionsRegistrar registrar) {
registerCollectionBinding(field.getType(), registrar, absColAnno, evalHelper);
}
});
}
}
else if (absColAnno != null) {
registerCollectionBinding(field.getType(), registrar, absColAnno, evalHelper);
}
}
private static void registerCollectionBinding(PsiType type,
DomExtensionsRegistrar registrar,
PsiAnnotation anno,
PsiConstantEvaluationHelper evalHelper) {
final boolean surroundWithTag = getBooleanAttribute(anno, "surroundWithTag", evalHelper);
if (surroundWithTag) return; // todo Set, List, Array
final String tagName = getStringAttribute(anno, "elementTag", evalHelper);
final String attrName = getStringAttribute(anno, "elementValueAttribute", evalHelper);
final PsiClass psiClass = getElementType(type);
if (tagName != null && attrName == null) {
registrar.registerCollectionChildrenExtension(new XmlName(tagName), SimpleTagValue.class);
}
else if (tagName != null) {
registrar.registerCollectionChildrenExtension(new XmlName(tagName), DomElement.class).addExtender(new DomExtender() {
@Override
public void registerExtensions(@NotNull DomElement domElement, @NotNull DomExtensionsRegistrar registrar) {
registrar.registerGenericAttributeValueChildExtension(new XmlName(attrName), String.class);
}
});
}
else if (psiClass != null) {
final PsiModifierList modifierList = psiClass.getModifierList();
final PsiAnnotation tagAnno = modifierList == null? null : modifierList.findAnnotation(Tag.class.getName());
final String classTagName = tagAnno == null? psiClass.getName() : getStringAttribute(tagAnno, "value", evalHelper);
if (classTagName != null) {
registrar.registerCollectionChildrenExtension(new XmlName(classTagName), DomElement.class).addExtender(new DomExtender() {
@Override
public void registerExtensions(@NotNull DomElement domElement, @NotNull DomExtensionsRegistrar registrar) {
registerXmlb(registrar, psiClass);
}
});
}
}
}
@Nullable
private static String getStringAttribute(final PsiAnnotation annotation,
final String name,
final PsiConstantEvaluationHelper evalHelper) {
final Object o = evalHelper.computeConstantExpression(annotation.findAttributeValue(name), false);
return o instanceof String && StringUtil.isNotEmpty((String)o)? (String)o : null;
}
private static boolean getBooleanAttribute(final PsiAnnotation annotation,
final String name,
final PsiConstantEvaluationHelper evalHelper) {
final Object o = evalHelper.computeConstantExpression(annotation.findAttributeValue(name), false);
return o instanceof Boolean? ((Boolean)o).booleanValue() : false;
}
@Nullable
public static PsiClass getElementType(final PsiType psiType) {
final PsiType elementType;
if (psiType instanceof PsiArrayType) elementType = ((PsiArrayType)psiType).getComponentType();
else if (psiType instanceof PsiClassType) {
final PsiType[] types = ((PsiClassType)psiType).getParameters();
elementType = types.length == 1? types[0] : null;
}
else elementType = null;
return PsiTypesUtil.getPsiClass(elementType);
}
public static Collection<String> getDependencies(IdeaPlugin ideaPlugin) {
Set<String> result = new HashSet<String>();
@@ -19,17 +19,18 @@ import com.intellij.openapi.project.Project;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.Function;
import com.intellij.util.containers.CollectionFactory;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xml.ConvertContext;
import com.intellij.util.xml.DomFileElement;
import com.intellij.util.xml.DomService;
import com.intellij.util.xml.ResolvingConverter;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.devkit.DevKitBundle;
import org.jetbrains.idea.devkit.dom.IdeaPlugin;
import org.jetbrains.idea.devkit.dom.PluginModule;
import java.util.Collection;
import java.util.List;
@@ -39,11 +40,6 @@ import java.util.Set;
* @author mike
*/
public class IdeaPluginConverter extends ResolvingConverter<IdeaPlugin> {
@NonNls private static final Set<String> PLATFORM_MODULES = CollectionFactory.newTroveSet("com.intellij.modules.platform",
"com.intellij.modules.lang",
"com.intellij.modules.vcs",
"com.intellij.modules.xdebugger",
"com.intellij.modules.xml");
@NotNull
public Collection<? extends IdeaPlugin> getVariants(final ConvertContext context) {
@@ -53,7 +49,13 @@ public class IdeaPluginConverter extends ResolvingConverter<IdeaPlugin> {
@NotNull
@Override
public Set<String> getAdditionalVariants(@NotNull final ConvertContext context) {
return PLATFORM_MODULES;
final THashSet<String> result = new THashSet<String>();
for (IdeaPlugin ideaPlugin : getVariants(context)) {
for (PluginModule module : ideaPlugin.getModules()) {
ContainerUtil.addIfNotNull(module.getValue().getValue(), result);
}
}
return result;
}
@Override
@@ -78,6 +80,10 @@ public class IdeaPluginConverter extends ResolvingConverter<IdeaPlugin> {
final String otherId = ideaPlugin.getPluginId();
if (otherId == null) continue;
if (otherId.equals(s)) return ideaPlugin;
for (PluginModule module : ideaPlugin.getModules()) {
final String moduleName = module.getValue().getValue();
if (moduleName != null && moduleName.equals(s)) return ideaPlugin;
}
}
return null;
}
@@ -2,7 +2,7 @@
<id>com.intellij.myPlugin</id>
<depends>com.intellij</depends>
<depends>com.intellij.modules.vcs</depends> <!-- a hack -->
<depends>com.intellij.modules.vcs</depends>
<depends>com.intellij.custom</depends>
<depends><error descr="Cannot resolve plugin com.intellij.xxx">com.intellij.xxx</error></depends>
@@ -67,6 +67,7 @@ public class PluginXmlFunctionalTest extends JavaCodeInsightFixtureTestCase {
final String root = "idea_core";
addPluginXml(root, "<idea-plugin>\n" +
" <id>com.intellij</id>\n" +
" <module value=\"com.intellij.modules.vcs\"/>\n" +
"</idea-plugin>");
addPluginXml("custom", "<idea-plugin>\n" +
" <id>com.intellij.custom</id>\n" +