Completion of dependency should honor <dependencyManagement> section
authorSergey Evdokimov <sergey.evdokimov@jetbrains.com>
Mon, 9 Sep 2013 11:33:13 +0000 (15:33 +0400)
committerSergey Evdokimov <sergey.evdokimov@jetbrains.com>
Mon, 9 Sep 2013 11:33:40 +0000 (15:33 +0400)
plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/model/completion/MavenDependenciesCompletionProvider.java
plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDependencySmartCompletionTest.java

index a080639b9818135b3d88d7aea94702a33271ce9c..21d35fa07485daafe7159eb5747a74505e2d445a 100644 (file)
@@ -6,15 +6,23 @@ import com.intellij.codeInsight.lookup.LookupElement;
 import com.intellij.codeInsight.lookup.LookupElementBuilder;
 import com.intellij.icons.AllIcons;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.impl.PsiImplUtil;
+import com.intellij.psi.xml.XmlFile;
 import com.intellij.psi.xml.XmlTag;
 import com.intellij.psi.xml.XmlText;
 import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.util.Processor;
 import com.intellij.util.xml.DomElement;
+import com.intellij.util.xml.DomFileElement;
 import com.intellij.util.xml.DomManager;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.maven.dom.MavenDomProjectProcessorUtils;
 import org.jetbrains.idea.maven.dom.model.MavenDomDependency;
+import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel;
 import org.jetbrains.idea.maven.indices.MavenProjectIndicesManager;
 
 /**
@@ -59,6 +67,29 @@ public class MavenDependenciesCompletionProvider extends CompletionContributor {
     }
   }
 
+  private static MavenDomDependency findManagedDependency(MavenDomProjectModel domModel, Project project,
+    @NotNull final String groupId, @NotNull final String artifactId) {
+
+    final Ref<MavenDomDependency> ref = new Ref<MavenDomDependency>();
+
+    MavenDomProjectProcessorUtils.processDependenciesInDependencyManagement(domModel,
+                                                                            new Processor<MavenDomDependency>() {
+                                                                              @Override
+                                                                              public boolean process(MavenDomDependency dependency) {
+                                                                                if (groupId.equals(dependency.getGroupId().getStringValue())
+                                                                                    &&
+                                                                                    artifactId.equals(
+                                                                                      dependency.getArtifactId().getStringValue())) {
+                                                                                  ref.set(dependency);
+                                                                                  return false;
+                                                                                }
+                                                                                return true;
+                                                                              }
+                                                                            }, project);
+
+    return ref.get();
+  }
+
   private static class MavenDependencyInsertHandler implements InsertHandler<LookupElement> {
 
     public static final InsertHandler<LookupElement> INSTANCE = new MavenDependencyInsertHandler();
@@ -71,20 +102,46 @@ public class MavenDependenciesCompletionProvider extends CompletionContributor {
       String groupId = s.substring(0, idx);
       String artifactId = s.substring(idx + 1);
 
+      int startOffset = context.getStartOffset();
 
-      String value = "<groupId>" + groupId + "</groupId>\n" +
-                     "<artifactId>" + artifactId + "</artifactId>\n" +
-                     "<version></version>";
+      PsiFile psiFile = context.getFile();
 
-      int startOffset = context.getStartOffset();
+      DomFileElement<MavenDomProjectModel> domModel = DomManager.getDomManager(context.getProject()).getFileElement((XmlFile)psiFile, MavenDomProjectModel.class);
+      if (domModel == null) return;
 
-      context.getDocument().replaceString(startOffset, context.getSelectionEndOffset(), value);
+      boolean shouldInvokeCompletion = false;
 
-      context.getEditor().getCaretModel().moveToOffset(startOffset + value.length() - 10);
+      MavenDomDependency managedDependency = findManagedDependency(domModel.getRootElement(), context.getProject(), groupId, artifactId);
+      if (managedDependency == null) {
+        String value = "<groupId>" + groupId + "</groupId>\n" +
+                       "<artifactId>" + artifactId + "</artifactId>\n" +
+                       "<version></version>";
 
-      context.commitDocument();
+        context.getDocument().replaceString(startOffset, context.getSelectionEndOffset(), value);
 
-      PsiFile psiFile = context.getFile();
+        context.getEditor().getCaretModel().moveToOffset(startOffset + value.length() - 10);
+
+        shouldInvokeCompletion = true;
+      }
+      else {
+        StringBuilder sb = new StringBuilder();
+        sb.append("<groupId>").append(groupId).append("</groupId>\n")
+          .append("<artifactId>").append(artifactId).append("</artifactId>\n");
+
+        String type = managedDependency.getType().getStringValue();
+        if (type != null && !type.equals("jar")) {
+          sb.append("<type>").append(type).append("</type>\n");
+        }
+
+        String classifier = managedDependency.getClassifier().getStringValue();
+        if (StringUtil.isNotEmpty(classifier)) {
+          sb.append("<classifier>").append(classifier).append("</classifier>\n");
+        }
+
+        context.getDocument().replaceString(startOffset, context.getSelectionEndOffset(), sb);
+      }
+
+      context.commitDocument();
 
       PsiElement e = psiFile.findElementAt(startOffset);
       while (e != null && (!(e instanceof XmlTag) || !"dependency".equals(((XmlTag)e).getName()))) {
@@ -95,12 +152,14 @@ public class MavenDependenciesCompletionProvider extends CompletionContributor {
         new ReformatCodeProcessor(psiFile.getProject(), psiFile, e.getTextRange(), true).run();
       }
 
-      context.setLaterRunnable(new Runnable() {
-        @Override
-        public void run() {
-          new CodeCompletionHandlerBase(CompletionType.BASIC).invokeCompletion(context.getProject(), context.getEditor());
-        }
-      });
+      if (shouldInvokeCompletion) {
+        context.setLaterRunnable(new Runnable() {
+          @Override
+          public void run() {
+            new CodeCompletionHandlerBase(CompletionType.BASIC).invokeCompletion(context.getProject(), context.getEditor());
+          }
+        });
+      }
     }
   }
 }
index 99b84d64c4911c64573b2b361a6ef809f839ea43..7642c1a57e3586cb29a6f7749583ee70a589a1ec 100644 (file)
@@ -49,4 +49,96 @@ public class MavenDependencySmartCompletionTest extends MavenDomWithIndicesTestC
                                        "</dependencies>\n"));
   }
 
+  public void testInsertManagedDependency() throws IOException {
+    createProjectPom("<groupId>test</groupId>\n" +
+                     "<artifactId>project</artifactId>\n" +
+                     "<version>1</version>\n" +
+
+                     "<dependencyManagement>\n" +
+                     "  <dependencies>\n" +
+                     "    <dependency>\n" +
+                     "      <groupId>junit</groupId>\n" +
+                     "      <artifactId>junit</artifactId>\n" +
+                     "      <version>4.0</version>\n" +
+                     "    </dependency>\n" +
+                     "  </dependencies>\n" +
+                     "</dependencyManagement>\n" +
+
+                     "<dependencies>\n" +
+                     "  <dependency>ju<caret></dependency>\n" +
+                     "</dependencies>\n");
+
+    configTest(myProjectPom);
+    myFixture.complete(CompletionType.SMART);
+
+    myFixture.checkResult(createPomXml("<groupId>test</groupId>\n" +
+                                       "<artifactId>project</artifactId>\n" +
+                                       "<version>1</version>\n" +
+                                       "<dependencyManagement>\n" +
+                                       "  <dependencies>\n" +
+                                       "    <dependency>\n" +
+                                       "      <groupId>junit</groupId>\n" +
+                                       "      <artifactId>junit</artifactId>\n" +
+                                       "      <version>4.0</version>\n" +
+                                       "    </dependency>\n" +
+                                       "  </dependencies>\n" +
+                                       "</dependencyManagement>\n" +
+                                       "<dependencies>\n" +
+                                       "    <dependency>\n" +
+                                       "        <groupId>junit</groupId>\n" +
+                                       "        <artifactId>junit</artifactId>\n" +
+                                       "    </dependency>\n" +
+                                       "</dependencies>\n"));
+  }
+
+  public void testInsertManagedDependencyWithTypeAndClassifier() throws IOException {
+    createProjectPom("<groupId>test</groupId>\n" +
+                     "<artifactId>project</artifactId>\n" +
+                     "<version>1</version>\n" +
+
+                     "<dependencyManagement>\n" +
+                     "  <dependencies>\n" +
+                     "    <dependency>\n" +
+                     "      <groupId>junit</groupId>\n" +
+                     "      <artifactId>junit</artifactId>\n" +
+                     "      <version>4.0</version>\n" +
+                     "      <type>test-jar</type>\n" +
+                     "      <classifier>sources</classifier>\n" +
+                     "    </dependency>\n" +
+                     "  </dependencies>\n" +
+                     "</dependencyManagement>\n" +
+
+                     "<dependencies>\n" +
+                     "  <dependency>ju<caret></dependency>\n" +
+                     "</dependencies>\n");
+
+    configTest(myProjectPom);
+    myFixture.complete(CompletionType.SMART);
+
+    myFixture.checkResult(createPomXml("<groupId>test</groupId>\n" +
+                                       "<artifactId>project</artifactId>\n" +
+                                       "<version>1</version>\n" +
+
+                                       "<dependencyManagement>\n" +
+                                       "  <dependencies>\n" +
+                                       "    <dependency>\n" +
+                                       "      <groupId>junit</groupId>\n" +
+                                       "      <artifactId>junit</artifactId>\n" +
+                                       "      <version>4.0</version>\n" +
+                                       "      <type>test-jar</type>\n" +
+                                       "      <classifier>sources</classifier>\n" +
+                                       "    </dependency>\n" +
+                                       "  </dependencies>\n" +
+                                       "</dependencyManagement>\n" +
+
+                                       "<dependencies>\n" +
+                                       "    <dependency>\n" +
+                                       "        <groupId>junit</groupId>\n" +
+                                       "        <artifactId>junit</artifactId>\n" +
+                                       "        <type>test-jar</type>\n" +
+                                       "        <classifier>sources</classifier>\n" +
+                                       "    </dependency>\n" +
+                                       "</dependencies>\n"));
+  }
+
 }