diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenFilteredPropertyPsiReference.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenFilteredPropertyPsiReference.java index e198e8647a16..4043b3e37b3a 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenFilteredPropertyPsiReference.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenFilteredPropertyPsiReference.java @@ -27,6 +27,7 @@ import org.jetbrains.idea.maven.dom.MavenDomUtil; import org.jetbrains.idea.maven.project.MavenProject; import java.util.List; +import java.util.Set; public class MavenFilteredPropertyPsiReference extends MavenPropertyPsiReference { public MavenFilteredPropertyPsiReference(MavenProject mavenProject, PsiElement element, String text, TextRange range) { @@ -49,13 +50,13 @@ public class MavenFilteredPropertyPsiReference extends MavenPropertyPsiReference } @Override - protected void collectVariants(List result) { - super.collectVariants(result); + protected void collectVariants(List result, Set variants) { + super.collectVariants(result, variants); for (String each : myMavenProject.getFilters()) { VirtualFile file = LocalFileSystem.getInstance().findFileByPath(each); if (file == null) continue; - collectPropertiesFileVariants(MavenDomUtil.getPropertiesFile(myProject, file), null, result); + collectPropertiesFileVariants(MavenDomUtil.getPropertiesFile(myProject, file), null, result, variants); } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenPropertyPsiReference.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenPropertyPsiReference.java index 43d555c9dcf8..e729f1463d9b 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenPropertyPsiReference.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenPropertyPsiReference.java @@ -213,6 +213,10 @@ public class MavenPropertyPsiReference extends MavenPsiReference { } } + if (mavenProject.getProperties().containsKey(myText)) { + return myElement; + } + if (myText.startsWith("settings.")) { return resolveSettingsModelProperty(); } @@ -287,11 +291,11 @@ public class MavenPropertyPsiReference extends MavenPsiReference { @NotNull public Object[] getVariants() { List result = new ArrayList(); - collectVariants(result); + collectVariants(result, new THashSet()); return ArrayUtil.toObjectArray(result); } - protected void collectVariants(final List result) { + protected void collectVariants(final List result, Set variants) { int prefixLength = 0; if (myText.startsWith("pom.")) { prefixLength = "pom.".length(); @@ -339,33 +343,30 @@ public class MavenPropertyPsiReference extends MavenPsiReference { } }); - collectPropertiesVariants(result); - collectSystemEnvProperties(MavenPropertiesVirtualFileSystem.SYSTEM_PROPERTIES_FILE, null, result); - collectSystemEnvProperties(MavenPropertiesVirtualFileSystem.ENV_PROPERTIES_FILE, "env.", result); + collectPropertiesVariants(result, variants); + collectSystemEnvProperties(MavenPropertiesVirtualFileSystem.SYSTEM_PROPERTIES_FILE, null, result, variants); + collectSystemEnvProperties(MavenPropertiesVirtualFileSystem.ENV_PROPERTIES_FILE, "env.", result, variants); MavenRunnerSettings runnerSettings = MavenRunner.getInstance(myProject).getSettings(); for (String prop : runnerSettings.getMavenProperties().keySet()) { - if (!isResultAlreadyContains(result, prop)) { + if (variants.add(prefix)) { result.add(LookupElementBuilder.create(prop).withIcon(PlatformIcons.PROPERTY_ICON)); } } for (String prop : MavenUtil.getPropertiesFromMavenOpts().keySet()) { - if (!isResultAlreadyContains(result, prop)) { + if (variants.add(prop)) { result.add(LookupElementBuilder.create(prop).withIcon(PlatformIcons.PROPERTY_ICON)); } } - } - private static boolean isResultAlreadyContains(List results, String propertyName) { - for (Object result : results) { - if (result instanceof LookupElement) { - if (((LookupElement)result).getLookupString().equals(propertyName)) { - return true; + for (Object key : myMavenProject.getProperties().keySet()) { + if (key instanceof String) { + String property = (String)key; + if (variants.add(property)) { + result.add(LookupElementBuilder.create(property).withIcon(PlatformIcons.PROPERTY_ICON)); } } } - - return false; } private static void addVariant(List result, String name, @NotNull Object element, @Nullable String prefix, @NotNull Icon icon) { @@ -382,28 +383,34 @@ public class MavenPropertyPsiReference extends MavenPsiReference { result.add(createLookupElement(element, nameWithPrefix, icon)); } - private void collectPropertiesVariants(final List result) { + private void collectPropertiesVariants(final List result, Set variants) { if (myProjectDom != null) { for (XmlTag xmlTag : MavenDomProjectProcessorUtils.collectProperties(myProjectDom, myProject)) { - result.add(createLookupElement(xmlTag, xmlTag.getName(), PlatformIcons.PROPERTY_ICON)); + String propertyName = xmlTag.getName(); + if (variants.add(propertyName)) { + result.add(createLookupElement(xmlTag, propertyName, PlatformIcons.PROPERTY_ICON)); + } } } } - private void collectSystemEnvProperties(String propertiesFileName, @Nullable String prefix, List result) { + private void collectSystemEnvProperties(String propertiesFileName, @Nullable String prefix, List result, Set variants) { VirtualFile virtualFile = MavenPropertiesVirtualFileSystem.getInstance().findFileByPath(propertiesFileName); PropertiesFile file = MavenDomUtil.getPropertiesFile(myProject, virtualFile); - collectPropertiesFileVariants(file, prefix, result); + collectPropertiesFileVariants(file, prefix, result, variants); } - protected static void collectPropertiesFileVariants(@Nullable PropertiesFile file, @Nullable String prefix, List result) { + protected static void collectPropertiesFileVariants(@Nullable PropertiesFile file, @Nullable String prefix, List result, Set variants) { if (file == null) return; for (IProperty each : file.getProperties()) { String name = each.getKey(); if (name != null) { if (prefix != null) name = prefix + name; - result.add(createLookupElement(each, name, PlatformIcons.PROPERTY_ICON)); + + if (variants.add(name)) { + result.add(createLookupElement(each, name, PlatformIcons.PROPERTY_ICON)); + } } } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenModelPropertiesPatcher.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenModelPropertiesPatcher.java new file mode 100644 index 000000000000..c16b84fba0b0 --- /dev/null +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenModelPropertiesPatcher.java @@ -0,0 +1,71 @@ +package org.jetbrains.idea.maven.plugins.api; + +import com.intellij.openapi.util.Pair; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.maven.model.MavenPlugin; + +import java.util.*; + +/** + * @author Sergey Evdokimov + */ +public class MavenModelPropertiesPatcher { + + private static volatile Map> ourMap; + + private static Map> getMap() { + Map> res = ourMap; + + if (res == null) { + res = new HashMap>(); + + for (MavenPluginDescriptor pluginDescriptor : MavenPluginDescriptor.EP_NAME.getExtensions()) { + if (pluginDescriptor.properties != null && pluginDescriptor.properties.length > 0) { + Pair pluginId = MavenPluginDescriptor.parsePluginId(pluginDescriptor.mavenId); + + String[] properties = new String[pluginDescriptor.properties.length]; + for (int i = 0; i < pluginDescriptor.properties.length; i++) { + properties[i] = pluginDescriptor.properties[i].name; + } + + Map groupMap = res.get(pluginId.second);// pluginId.second is artifactId + if (groupMap == null) { + groupMap = new HashMap(); + res.put(pluginId.second, groupMap); + } + + groupMap.put(pluginId.first, properties); // pluginId.first is groupId + } + } + + ourMap = res; + } + + return res; + } + + /* + * Add properties those should be added by plugins. + */ + public static void patch(Properties modelProperties, @Nullable Collection plugins) { + if (plugins == null) return; + + Map> map = getMap(); + + for (MavenPlugin plugin : plugins) { + Map groupMap = map.get(plugin.getArtifactId()); + if (groupMap != null) { + String[] properties = groupMap.get(plugin.getGroupId()); + + if (properties != null) { + for (String property : properties) { + if (!modelProperties.containsKey(property)) { + modelProperties.setProperty(property, ""); + } + } + } + } + } + } + +} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenPluginDescriptor.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenPluginDescriptor.java index 9176bd9f40a1..cb99a4aef9b5 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenPluginDescriptor.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenPluginDescriptor.java @@ -17,6 +17,7 @@ package org.jetbrains.idea.maven.plugins.api; import com.intellij.openapi.extensions.AbstractExtensionPointBean; import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.util.Pair; import com.intellij.util.xml.Required; import com.intellij.util.xmlb.annotations.AbstractCollection; import com.intellij.util.xmlb.annotations.Attribute; @@ -38,9 +39,17 @@ public class MavenPluginDescriptor extends AbstractExtensionPointBean { @AbstractCollection(surroundWithTag = false) public Param[] params; - /** - * @author Sergey Evdokimov - */ + @Property(surroundWithTag = false) + @AbstractCollection(surroundWithTag = false) + public ModelProperty[] properties; + + @Tag("property") + public static class ModelProperty { + @Attribute("name") + @Required + public String name; + } + @Tag("param") public static class Param { @@ -58,4 +67,14 @@ public class MavenPluginDescriptor extends AbstractExtensionPointBean { public String refProvider; } + + public static Pair parsePluginId(String mavenId) { + int idx = mavenId.indexOf(':'); + if (idx <= 0 || idx == mavenId.length() - 1 || mavenId.lastIndexOf(':') != idx) { + throw new RuntimeException("Failed to parse mavenId: " + mavenId + " (mavenId should has format 'groupId:artifactId')"); + } + + return new Pair(mavenId.substring(0, idx), mavenId.substring(idx + 1)); + } + } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenPluginParamReferenceContributor.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenPluginParamReferenceContributor.java index 9739c9a993dc..0623885dc9ee 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenPluginParamReferenceContributor.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenPluginParamReferenceContributor.java @@ -63,7 +63,9 @@ public class MavenPluginParamReferenceContributor extends PsiReferenceContributo res = new HashMap(); for (MavenPluginDescriptor pluginDescriptor : MavenPluginDescriptor.EP_NAME.getExtensions()) { - Pair pluginId = parsePluginId(pluginDescriptor.mavenId); + if (pluginDescriptor.params == null) continue; + + Pair pluginId = MavenPluginDescriptor.parsePluginId(pluginDescriptor.mavenId); for (MavenPluginDescriptor.Param param : pluginDescriptor.params) { String[] paramPath = param.name.split("/"); @@ -93,15 +95,6 @@ public class MavenPluginParamReferenceContributor extends PsiReferenceContributo return res; } - private static Pair parsePluginId(String mavenId) { - int idx = mavenId.indexOf(':'); - if (idx <= 0 || idx == mavenId.length() - 1 || mavenId.lastIndexOf(':') != idx) { - throw new RuntimeException("Failed to parse mavenId: " + mavenId + " (mavenId should has format 'groupId:artifactId')"); - } - - return new Pair(mavenId.substring(0, idx), mavenId.substring(idx + 1)); - } - @NotNull private static V getOrCreate(Map map, K key) { Map res = (Map)map.get(key); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java index 414f313ea2b7..069067126675 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java @@ -37,6 +37,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.importing.MavenExtraArtifactType; import org.jetbrains.idea.maven.importing.MavenImporter; import org.jetbrains.idea.maven.model.*; +import org.jetbrains.idea.maven.plugins.api.MavenModelPropertiesPatcher; import org.jetbrains.idea.maven.server.MavenEmbedderWrapper; import org.jetbrains.idea.maven.server.NativeMavenProjectHolder; import org.jetbrains.idea.maven.utils.*; @@ -154,6 +155,8 @@ public class MavenProject { doSetResolvedAttributes(newState, readerResult, resetArtifacts); + MavenModelPropertiesPatcher.patch(newState.myProperties, newState.myPlugins); + newState.myModulesPathsAndNames = collectModulePathsAndNames(model, getDirectory()); Collection newProfiles = collectProfilesIds(model.getProfiles()); if (resetProfiles || newState.myProfilesIds == null) { diff --git a/plugins/maven/src/main/resources/META-INF/plugin.xml b/plugins/maven/src/main/resources/META-INF/plugin.xml index 838753499621..1130f5ac4f6a 100644 --- a/plugins/maven/src/main/resources/META-INF/plugin.xml +++ b/plugins/maven/src/main/resources/META-INF/plugin.xml @@ -147,6 +147,14 @@ + + + + + + + + diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/plugins/jgitBuildnumber/JGitBuildNumberTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/plugins/jgitBuildnumber/JGitBuildNumberTest.java new file mode 100644 index 000000000000..8ed34f3de824 --- /dev/null +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/plugins/jgitBuildnumber/JGitBuildNumberTest.java @@ -0,0 +1,109 @@ +package org.jetbrains.idea.maven.plugins.jgitBuildnumber; + +import org.jetbrains.idea.maven.dom.MavenDomTestCase; + +import java.io.IOException; +import java.util.List; + +/** + * @author Sergey Evdokimov + */ +public class JGitBuildNumberTest extends MavenDomTestCase { + + public void testCompletion() throws Exception { + importProject("test\n" + + "project\n" + + "1\n" + + "\n" + + " ${}" + + "\n" + + " \n" + + " \n" + + " \n" + + " ru.concerteza.buildnumber\n" + + " maven-jgit-buildnumber-plugin\n" + + " \n" + + " \n" + + " \n" + ); + + createProjectPom("test\n" + + "project\n" + + "1\n" + + "\n" + + " ${}" + + "\n" + + " \n" + + " \n" + + " \n" + + " ru.concerteza.buildnumber\n" + + " maven-jgit-buildnumber-plugin\n" + + " \n" + + " \n" + + " \n" + ); + + List variants = getCompletionVariants(myProjectPom); + + assertContain(variants, "git.commitsCount"); + } + + public void testHighlighting() throws Exception { + importProject("test\n" + + "project\n" + + "1\n" + + "\n" + + " ${git.commitsCount}" + + " ${git.commitsCount__}" + + "\n" + + " \n" + + " \n" + + " \n" + + " ru.concerteza.buildnumber\n" + + " maven-jgit-buildnumber-plugin\n" + + " \n" + + " \n" + + " \n" + ); + + createProjectPom("test\n" + + "project\n" + + "1\n" + + "\n" + + " ${git.commitsCount}" + + " ${git.commitsCount__}" + + "\n" + + " \n" + + " \n" + + " \n" + + " ru.concerteza.buildnumber\n" + + " maven-jgit-buildnumber-plugin\n" + + " \n" + + " \n" + + " \n" + ); + + checkHighlighting(myProjectPom); + } + + public void testNoPluginHighlighting() throws Exception { + importProject("test\n" + + "project\n" + + "1\n" + + "\n" + + " ${git.commitsCount}" + + "\n" + ); + + createProjectPom("test\n" + + "project\n" + + "1\n" + + "\n" + + " ${git.commitsCount}" + + "\n"); + + checkHighlighting(myProjectPom); + } + + +}