plugin.xml:

correctly determine extension short name
don't red-highlight hacky non-existing vcs plugin reference
This commit is contained in:
Peter Gromov
2008-10-15 14:01:10 +04:00
parent 2335679d8b
commit c68f726521
7 changed files with 173 additions and 42 deletions
@@ -161,3 +161,5 @@ project.title=Plugin Project
no.java.sdk.for.idea.sdk.found=No Java SDK of appropriate version found. In addition to the IDEA JDK, you need to define a JSDK with the same Java version ({0}).
no.idea.sdk.version.found=Failed to detect JDK version required for IDEA JDK.
group.PluginDeployActions.text=Plugin Deployment Actions
error.cannot.resolve.plugin=Cannot resolve plugin {0}
+2 -2
View File
@@ -13,10 +13,10 @@ import org.jetbrains.idea.devkit.dom.impl.ExtensionNsConverter;
public interface Extensions extends DomElement {
@NotNull
@Attribute("defaultExtensionNs")
@Convert(ExtensionNsConverter.class)
@Convert(value=ExtensionNsConverter.class, soft=true)
GenericAttributeValue<IdeaPlugin> getDefaultExtensionNs();
@NotNull
@Convert(ExtensionNsConverter.class)
@Convert(value=ExtensionNsConverter.class, soft=true)
GenericAttributeValue<IdeaPlugin> getXmlns();
}
@@ -1,9 +1,11 @@
package org.jetbrains.idea.devkit.dom.impl;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.xml.XmlElement;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xml.*;
import com.intellij.util.xml.reflect.DomExtender;
import com.intellij.util.xml.reflect.DomExtension;
@@ -11,9 +13,12 @@ import com.intellij.util.xml.reflect.DomExtensionsRegistrar;
import com.intellij.util.xmlb.annotations.Attribute;
import com.intellij.util.xmlb.annotations.Tag;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.devkit.dom.*;
import java.util.*;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
/**
* @author mike
@@ -31,56 +36,71 @@ public class ExtensionDomExtender extends DomExtender<Extensions> {
if (ideaPlugin == null) return;
registerExtensions(extensions, ideaPlugin, registrar, psiManager);
IdeaPlugin plugin = extensions.getDefaultExtensionNs().getValue();
if (plugin == null) plugin = extensions.getXmlns().getValue();
if (plugin != null) {
registerExtensions(extensions, plugin, registrar, psiManager);
String prefix = extensions.getDefaultExtensionNs().getStringValue();
if (prefix == null) prefix = extensions.getXmlns().getStringValue();
if (prefix != null) {
prefix += ".";
} else {
prefix = "";
}
final Collection<String> dependencies = getDependencies(ideaPlugin);
ContainerUtil.addIfNotNull(ideaPlugin.getPluginId(), dependencies);
for (IdeaPlugin plugin : IdeaPluginConverter.collectAllVisiblePlugins(extensions.getRoot().getFile())) {
final String value = plugin.getPluginId();
if (value != null && dependencies.contains(value)) {
registerExtensions(prefix, plugin, registrar, psiManager);
}
}
}
private static void registerExtensions(final Extensions extensions, final IdeaPlugin plugin, final DomExtensionsRegistrar registrar,
private static void registerExtensions(final String prefix, final IdeaPlugin plugin, final DomExtensionsRegistrar registrar,
final PsiManager psiManager) {
final String pluginId = plugin.getPluginId();
for (ExtensionPoints points : plugin.getExtensionPoints()) {
for (ExtensionPoint point : points.getExtensionPoints()) {
registerExtensionPoint(registrar, point, psiManager);
registerExtensionPoint(registrar, point, psiManager, prefix, pluginId);
}
}
}
private static void registerExtensionPoint(final DomExtensionsRegistrar registrar, final ExtensionPoint extensionPoint, final PsiManager manager) {
final String epName = extensionPoint.getName().getStringValue();
if (epName != null) {
final DomExtension domExtension = registrar.registerCollectionChildrenExtension(new XmlName(epName), Extension.class);
domExtension.putUserData(DomExtension.KEY_DECLARATION, extensionPoint);
domExtension.addExtender(new DomExtender() {
public void registerExtensions(@NotNull final DomElement domElement, @NotNull final DomExtensionsRegistrar registrar) {
final String interfaceName = extensionPoint.getInterface().getStringValue();
if (interfaceName != null) {
registrar.registerGenericAttributeValueChildExtension(new XmlName("implementation"), PsiClass.class).setConverter(
CLASS_CONVERTER);
private static void registerExtensionPoint(final DomExtensionsRegistrar registrar, final ExtensionPoint extensionPoint, final PsiManager manager, String prefix, @Nullable String pluginId) {
String epName = extensionPoint.getName().getStringValue();
if (epName == null) epName = extensionPoint.getQualifiedName().getStringValue();
if (epName == null) return;
final PsiClass implClass =
JavaPsiFacade.getInstance(manager.getProject()).findClass(interfaceName, GlobalSearchScope.allScope(manager.getProject()));
if (implClass != null) {
registerXmlb(registrar, implClass);
}
if (StringUtil.isNotEmpty(pluginId)) epName = pluginId + "." + epName;
if (!epName.startsWith(prefix)) return;
final DomExtension domExtension = registrar.registerCollectionChildrenExtension(new XmlName(epName.substring(prefix.length())), Extension.class);
domExtension.putUserData(DomExtension.KEY_DECLARATION, extensionPoint);
domExtension.addExtender(new DomExtender() {
public void registerExtensions(@NotNull final DomElement domElement, @NotNull final DomExtensionsRegistrar registrar) {
final String interfaceName = extensionPoint.getInterface().getStringValue();
if (interfaceName != null) {
registrar.registerGenericAttributeValueChildExtension(new XmlName("implementation"), PsiClass.class).setConverter(
CLASS_CONVERTER);
final PsiClass implClass =
JavaPsiFacade.getInstance(manager.getProject()).findClass(interfaceName, GlobalSearchScope.allScope(manager.getProject()));
if (implClass != null) {
registerXmlb(registrar, implClass);
}
else {
final String beanClassName = extensionPoint.getBeanClass().getStringValue();
if (beanClassName != null) {
final PsiClass beanClass =
JavaPsiFacade.getInstance(manager.getProject()).findClass(beanClassName, GlobalSearchScope.allScope(manager.getProject()));
}
else {
final String beanClassName = extensionPoint.getBeanClass().getStringValue();
if (beanClassName != null) {
final PsiClass beanClass =
JavaPsiFacade.getInstance(manager.getProject()).findClass(beanClassName, GlobalSearchScope.allScope(manager.getProject()));
if (beanClass != null) {
registerXmlb(registrar, beanClass);
}
if (beanClass != null) {
registerXmlb(registrar, beanClass);
}
}
}
});
}
}
});
}
private static void registerXmlb(final DomExtensionsRegistrar registrar, final PsiClass beanClass) {
@@ -19,13 +19,12 @@ import com.intellij.util.xml.ResolvingConverter;
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.module.PluginModuleType;
import org.jetbrains.idea.devkit.projectRoots.IdeaJdk;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.*;
/**
* @author mike
@@ -33,9 +32,18 @@ import java.util.List;
public class IdeaPluginConverter extends ResolvingConverter<IdeaPlugin> {
@NotNull
public Collection<? extends IdeaPlugin> getVariants(final ConvertContext context) {
final XmlFile xmlFile = context.getFile();
return collectAllVisiblePlugins(context.getFile());
}
return collectAllVisiblePlugins(xmlFile);
@NotNull
@Override
public Set<String> getAdditionalVariants(@NotNull final ConvertContext context) {
return Collections.singleton("com.intellij.modules.vcs"); //todo this is a hack
}
@Override
public String getErrorMessage(@Nullable final String s, final ConvertContext context) {
return DevKitBundle.message("error.cannot.resolve.plugin", s);
}
public static Collection<IdeaPlugin> collectAllVisiblePlugins(final XmlFile xmlFile) {
@@ -0,0 +1,9 @@
<idea-plugin>
<id>com.intellij.myPlugin</id>
<depends>com.intellij</depends>
<depends>com.intellij.modules.vcs</depends> <!-- a hack -->
<depends>com.intellij.custom</depends>
<depends><error descr="Cannot resolve plugin com.intellij.xxx">com.intellij.xxx</error></depends>
</idea-plugin>
@@ -0,0 +1,15 @@
<idea-plugin>
<id>com.intellij.myPlugin</id>
<extensionPoints>
<extensionPoint name="foo.bar"/>
</extensionPoints>
<depends>com.intellij.custom</depends>
<extensions defaultExtensionNs="com.intellij">
<myPlugin.foo.bar/>
<completion.contributor/>
<custom.custom/>
<<error descr="Element custom.error is not allowed here">custom.error</error>/>
</extensions>
</idea-plugin>
@@ -0,0 +1,77 @@
/*
* Copyright (c) 2000-2005 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package org.jetbrains.idea.devkit.codeInsight;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase;
import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
import com.intellij.testFramework.fixtures.TempDirTestFixture;
import org.jetbrains.idea.devkit.DevKitInspectionToolProvider;
import java.io.IOException;
/**
* @author peter
*/
public class PluginXmlFunctionalTest extends CodeInsightFixtureTestCase {
private TempDirTestFixture myTempDirFixture;
@Override
protected void setUp() throws Exception {
super.setUp();
myTempDirFixture = IdeaTestFixtureFactory.getFixtureFactory().createTempDirTestFixture();
myFixture.enableInspections(new DevKitInspectionToolProvider());
}
@Override
protected String getBasePath() {
return "/svnPlugins/devkit/testData/codeInsight";
}
public void testExtensionsHighlighting() throws Throwable {
final String root = "idea_core";
addPluginXml(root, "<idea-plugin>\n" +
" <id>com.intellij</id>\n" +
" <extensionPoints>\n" +
" <extensionPoint name=\"completion.contributor\"/>\n" +
" </extensionPoints>\n" +
"</idea-plugin>");
addPluginXml("custom", "<idea-plugin>\n" +
" <id>com.intellij.custom</id>\n" +
" <extensionPoints>\n" +
" <extensionPoint name=\"custom\"/>\n" +
" </extensionPoints>\n" +
"</idea-plugin>");
myFixture.configureFromExistingVirtualFile(myFixture.copyFileToProject(getTestName(false) + ".xml", "META-INF/plugin.xml"));
myFixture.checkHighlighting(false, false, false);
}
public void testDependsHighlighting() throws Throwable {
final String root = "idea_core";
addPluginXml(root, "<idea-plugin>\n" +
" <id>com.intellij</id>\n" +
"</idea-plugin>");
addPluginXml("custom", "<idea-plugin>\n" +
" <id>com.intellij.custom</id>\n" +
"</idea-plugin>");
myFixture.configureFromExistingVirtualFile(myFixture.copyFileToProject(getTestName(false) + ".xml", "META-INF/plugin.xml"));
myFixture.checkHighlighting(false, false, false);
}
private void addPluginXml(final String root, final String text) throws IOException {
myTempDirFixture.createFile(root +
"/META-INF/plugin.xml", text);
new WriteCommandAction(getProject()) {
protected void run(Result result) throws Throwable {
PsiTestUtil.addSourceContentToRoots(myModule, myTempDirFixture.getFile(root));
}
}.execute();
}
}