diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenFixedValueReferenceProvider.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenFixedValueReferenceProvider.java new file mode 100644 index 000000000000..80a27c30b0b3 --- /dev/null +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenFixedValueReferenceProvider.java @@ -0,0 +1,69 @@ +package org.jetbrains.idea.maven.plugins.api; + +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import com.intellij.util.ProcessingContext; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.maven.dom.MavenPropertyResolver; +import org.jetbrains.idea.maven.dom.model.MavenDomConfiguration; + +import java.util.Arrays; +import java.util.regex.Matcher; + +/** + * @author Sergey Evdokimov + */ +public class MavenFixedValueReferenceProvider implements MavenParamReferenceProvider, MavenSoftAwareReferenceProvider { + + private final String[] myValues; + + private boolean mySoft = false; + + public MavenFixedValueReferenceProvider(String[] values) { + myValues = values; + } + + @Override + public PsiReference[] getReferencesByElement(@NotNull PsiElement element, + @NotNull MavenDomConfiguration domCfg, + @NotNull ProcessingContext context) { + ElementManipulator manipulator = ElementManipulators.getManipulator(element); + TextRange range = manipulator.getRangeInElement(element); + + String text = range.substring(element.getText()); + Matcher matcher = MavenPropertyResolver.PATTERN.matcher(text); + if (matcher.find()) { + return PsiReference.EMPTY_ARRAY; + } + + return new PsiReference[] { + new PsiReferenceBase(element, mySoft) { + @Nullable + @Override + public PsiElement resolve() { + if (mySoft) { + return null; + } + + if (Arrays.asList(myValues).contains(getValue())) { + return getElement(); + } + + return null; + } + + @NotNull + @Override + public Object[] getVariants() { + return myValues; + } + } + }; + } + + @Override + public void setSoft(boolean soft) { + mySoft = soft; + } +} 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 88607dd531d5..02ae4b91f05d 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 @@ -66,6 +66,12 @@ public class MavenPluginDescriptor extends AbstractExtensionPointBean { @Attribute("refProvider") public String refProvider; + @Attribute("values") + public String values; + + @Attribute("soft") + public Boolean soft; + /** * Language to inject. */ diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenPluginParamInfo.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenPluginParamInfo.java index a5a754185ddb..46197e07a7c3 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenPluginParamInfo.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenPluginParamInfo.java @@ -19,6 +19,7 @@ import org.jetbrains.idea.maven.dom.model.*; import java.util.HashMap; import java.util.Map; +import java.util.StringTokenizer; /** * @author Sergey Evdokimov @@ -173,6 +174,7 @@ public class MavenPluginParamInfo { private volatile boolean myLanguageInitialized; private Language myLanguageInstance; + private volatile boolean myProviderInitialized; private volatile MavenParamReferenceProvider myProviderInstance; private ParamInfo(ClassLoader classLoader, MavenPluginDescriptor.Param param) { @@ -201,42 +203,61 @@ public class MavenPluginParamInfo { } public MavenParamReferenceProvider getProviderInstance() { - MavenParamReferenceProvider res = myProviderInstance; + if (!myProviderInitialized) { + MavenParamReferenceProvider res = null; - if (res == null) { - if (myParam.refProvider == null) { - return null; + if (myParam.refProvider != null) { + assert myParam.values == null : myParam.name; + + Object instance; + + try { + instance = myClassLoader.loadClass(myParam.refProvider).newInstance(); + } + catch (Exception e) { + throw new RuntimeException("Failed to create reference provider instance", e); + } + + if (instance instanceof MavenParamReferenceProvider) { + res = (MavenParamReferenceProvider)instance; + } + else { + final PsiReferenceProvider psiReferenceProvider = (PsiReferenceProvider)instance; + + res = new MavenParamReferenceProvider() { + @Override + public PsiReference[] getReferencesByElement(@NotNull PsiElement element, + @NotNull MavenDomConfiguration domCfg, + @NotNull ProcessingContext context) { + return psiReferenceProvider.getReferencesByElement(element, context); + } + }; + } + } + else if (myParam.values != null) { + StringTokenizer st = new StringTokenizer(myParam.values, " ,;"); + int n = st.countTokens(); + + if (n == 0) throw new RuntimeException("Incorrect value of 'values' attribute for param " + myParam.name); + + String[] values = new String[n]; + + for (int i = 0; i < n; i++) { + values[i] = st.nextToken(); + } + + res = new MavenFixedValueReferenceProvider(values); } - Object instance; - - try { - instance = myClassLoader.loadClass(myParam.refProvider).newInstance(); - } - catch (Exception e) { - throw new RuntimeException("Failed to create reference provider instance", e); - } - - if (instance instanceof MavenParamReferenceProvider) { - res = (MavenParamReferenceProvider)instance; - } - else { - final PsiReferenceProvider psiReferenceProvider = (PsiReferenceProvider)instance; - - res = new MavenParamReferenceProvider() { - @Override - public PsiReference[] getReferencesByElement(@NotNull PsiElement element, - @NotNull MavenDomConfiguration domCfg, - @NotNull ProcessingContext context) { - return psiReferenceProvider.getReferencesByElement(element, context); - } - }; + if (res != null && myParam.soft != null) { + ((MavenSoftAwareReferenceProvider)res).setSoft(myParam.soft); } myProviderInstance = res; + myProviderInitialized = true; } - return res; + return myProviderInstance; } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenSoftAwareReferenceProvider.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenSoftAwareReferenceProvider.java new file mode 100644 index 000000000000..bd2f631529f3 --- /dev/null +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenSoftAwareReferenceProvider.java @@ -0,0 +1,10 @@ +package org.jetbrains.idea.maven.plugins.api; + +/** + * @author Sergey Evdokimov + */ +public interface MavenSoftAwareReferenceProvider { + + void setSoft(boolean soft); + +} diff --git a/plugins/maven/src/main/resources/META-INF/plugin.xml b/plugins/maven/src/main/resources/META-INF/plugin.xml index d1c8591dee70..659950324baf 100644 --- a/plugins/maven/src/main/resources/META-INF/plugin.xml +++ b/plugins/maven/src/main/resources/META-INF/plugin.xml @@ -161,6 +161,11 @@ + + + + + diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/plugins/MavenParameterFixedValueTest.groovy b/plugins/maven/src/test/java/org/jetbrains/idea/maven/plugins/MavenParameterFixedValueTest.groovy new file mode 100644 index 000000000000..7c8ab1136dc6 --- /dev/null +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/plugins/MavenParameterFixedValueTest.groovy @@ -0,0 +1,41 @@ +package org.jetbrains.idea.maven.plugins + +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase + +/** + * @author Sergey Evdokimov + */ +class MavenParameterFixedValueTest extends LightCodeInsightFixtureTestCase { + + public void testCompletion() { + myFixture.configureByText("pom.xml", """ + + + 4.0.0 + + simpleMaven + simpleMaven + 1.0 + + + + + maven-compiler-plugin + + + + + + + + +""") + + myFixture.completeBasic() + + assertSameElements(['reuseCreated', 'reuseSame', 'alwaysNew'], myFixture.lookupElementStrings) + } + +}