added support for multi-file libraries to 'Add Library to Project' dialog, reused...
authornik <Nikolay.Chashnikov@jetbrains.com>
Thu, 6 Aug 2015 16:04:40 +0000 (19:04 +0300)
committernik <Nikolay.Chashnikov@jetbrains.com>
Fri, 7 Aug 2015 07:44:24 +0000 (10:44 +0300)
12 files changed:
java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddExternalLibraryToDependenciesQuickFix.java
java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/JetBrainsAnnotationsExternalLibraryResolver.java
java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/LocateLibraryDialog.form
java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/LocateLibraryDialog.java
java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/OrderEntryFix.java
java/java-impl/src/com/intellij/codeInsight/daemon/quickFix/ExternalLibraryDescriptor.java
java/java-impl/src/com/intellij/codeInsight/daemon/quickFix/ExternalLibraryResolver.java
java/java-impl/src/com/intellij/codeInspection/concurrencyAnnotations/JCiPExternalLibraryResolver.java
java/java-impl/src/com/intellij/codeInspection/inferNullity/InferNullityAnnotationsAction.java
plugins/junit/src/com/intellij/execution/junit/codeInsight/JUnitExternalLibraryResolver.java
plugins/testng/src/com/theoryinpractice/testng/intention/TestNGExternalLibraryResolver.java
resources-en/src/messages/QuickFixBundle.properties

index 97c33ac6bbf2217599dbd21cf0267f466b272dda..c1625afe6ae4c7ea7f4aed65d97c086e866fc5ad 100644 (file)
@@ -67,7 +67,9 @@ class AddExternalLibraryToDependenciesQuickFix extends OrderEntryFix {
 
   @Override
   public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
-    List<String> classesRoots = myLibraryDescriptor.locateLibraryClassesRoots(myCurrentModule);
+    List<String> defaultRoots = myLibraryDescriptor.getLibraryClassesRoots();
+    LocateLibraryDialog dialog = new LocateLibraryDialog(myCurrentModule, defaultRoots, myLibraryDescriptor.getPresentableName());
+    List<String> classesRoots = dialog.showAndGetResult();
     if (!classesRoots.isEmpty()) {
       String libraryName = classesRoots.size() > 1 ? myLibraryDescriptor.getPresentableName() : null;
       addJarsToRootsAndImportClass(classesRoots, libraryName, myCurrentModule, editor, myReference,
index e5b6a3c09e7dd442ea524a98b71e6c193d50cd60..9d70fdc93d4967478271a6e4564e3ff28acea9ed 100644 (file)
@@ -18,32 +18,61 @@ package com.intellij.codeInsight.daemon.impl.quickfix;
 import com.intellij.codeInsight.AnnotationUtil;
 import com.intellij.codeInsight.daemon.quickFix.ExternalLibraryDescriptor;
 import com.intellij.codeInsight.daemon.quickFix.ExternalLibraryResolver;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.module.EffectiveLanguageLevelUtil;
 import com.intellij.openapi.module.Module;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.pom.java.LanguageLevel;
 import com.intellij.util.ThreeState;
-import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.io.File;
+import java.util.Collections;
 import java.util.List;
 
 /**
  * @author nik
  */
 public class JetBrainsAnnotationsExternalLibraryResolver extends ExternalLibraryResolver {
-  private static final ExternalLibraryDescriptor ANNOTATIONS = new ExternalLibraryDescriptor("com.intellij", "annotations", null) {
-    @NotNull
-    @Override
-    public List<String> locateLibraryClassesRoots(@NotNull Module contextModule) {
-      return ContainerUtil.createMaybeSingletonList(OrderEntryFix.locateAnnotationsJar(contextModule));
-    }
-  };
+  private static final ExternalLibraryDescriptor JAVA5 = new JetBrainsAnnotationsLibraryDescriptor(false);
+  private static final ExternalLibraryDescriptor JAVA8 = new JetBrainsAnnotationsLibraryDescriptor(true);
 
   @Nullable
   @Override
-  public ExternalClassResolveResult resolveClass(@NotNull String shortClassName, @NotNull ThreeState isAnnotation) {
+  public ExternalClassResolveResult resolveClass(@NotNull String shortClassName, @NotNull ThreeState isAnnotation, @NotNull Module contextModule) {
     if (AnnotationUtil.isJetbrainsAnnotation(shortClassName)) {
-      return new ExternalClassResolveResult("org.jetbrains.annotations." + shortClassName, ANNOTATIONS);
+      ExternalLibraryDescriptor libraryDescriptor = getAnnotationsLibraryDescriptor(contextModule);
+      return new ExternalClassResolveResult("org.jetbrains.annotations." + shortClassName, libraryDescriptor);
     }
     return null;
   }
+
+  @NotNull
+  public static ExternalLibraryDescriptor getAnnotationsLibraryDescriptor(@NotNull Module contextModule) {
+    boolean java8 = EffectiveLanguageLevelUtil.getEffectiveLanguageLevel(contextModule).isAtLeast(LanguageLevel.JDK_1_8);
+    return java8 ? JAVA8 : JAVA5;
+  }
+
+  private static class JetBrainsAnnotationsLibraryDescriptor extends ExternalLibraryDescriptor {
+    private boolean myJava8;
+
+    public JetBrainsAnnotationsLibraryDescriptor(boolean java8) {
+      super("com.intellij", "annotations", null);
+      myJava8 = java8;
+    }
+
+    @NotNull
+    @Override
+    public List<String> getLibraryClassesRoots() {
+      List<String> paths;
+      if (myJava8) {
+        paths = Collections.singletonList(FileUtil.toSystemIndependentName(new File(PathManager.getHomePath(), "redist/annotations-java8.jar").getAbsolutePath()));
+      }
+      else {
+        paths = Collections.singletonList(FileUtil.toSystemIndependentName(new File(PathManager.getLibPath(), "annotations.jar").getAbsolutePath()));
+      }
+      return paths;
+    }
+  }
 }
index 51a40ab236b6482fc1c5dffd29b89ba7987ce62d..a61102481439641b40cf2fa74e2378803927bc41 100644 (file)
@@ -1,71 +1,41 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.codeInsight.daemon.impl.quickfix.LocateLibraryDialog">
-  <grid id="cbd77" binding="contentPane" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+  <grid id="cbd77" binding="myContentPane" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
     <margin top="0" left="0" bottom="0" right="0"/>
     <constraints>
-      <xy x="48" y="54" width="623" height="297"/>
+      <xy x="48" y="54" width="623" height="113"/>
     </constraints>
     <properties/>
     <border type="none"/>
     <children>
-      <grid id="e3588" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
-        <margin top="0" left="0" bottom="0" right="0"/>
+      <component id="7d053" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myCopyToDir">
         <constraints>
-          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="4" hsize-policy="7" anchor="1" fill="1" indent="0" use-parent-layout="false"/>
+          <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="2" use-parent-layout="false"/>
         </constraints>
         <properties/>
-        <border type="none"/>
-        <children>
-          <component id="feb4c" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myLibraryFile">
-            <constraints>
-              <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false">
-                <minimum-size width="100" height="-1"/>
-                <preferred-size width="300" height="-1"/>
-              </grid>
-            </constraints>
-            <properties/>
-          </component>
-          <component id="7d053" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myCopyToDir">
-            <constraints>
-              <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
-            </constraints>
-            <properties/>
-          </component>
-          <component id="ec66c" class="javax.swing.JRadioButton" binding="myCopyToRadioButton" default-binding="true">
-            <constraints>
-              <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-            </constraints>
-            <properties>
-              <text resource-bundle="messages/QuickFixBundle" key="add.library.copy.to"/>
-            </properties>
-          </component>
-          <component id="4d13d" class="javax.swing.JLabel" binding="myFileLabel">
-            <constraints>
-              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="1" use-parent-layout="false"/>
-            </constraints>
-            <properties>
-              <text resource-bundle="messages/QuickFixBundle" key="add.library.file"/>
-            </properties>
-          </component>
-          <component id="204d7" class="javax.swing.JRadioButton" binding="myAddThisFileRadioButton" default-binding="true">
-            <constraints>
-              <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-            </constraints>
-            <properties>
-              <text resource-bundle="messages/QuickFixBundle" key="add.library.add.this"/>
-            </properties>
-          </component>
-        </children>
-      </grid>
-      <component id="a8ddb" class="javax.swing.JTextPane" binding="myDescription">
+      </component>
+      <component id="e9cf2" class="com.intellij.ui.components.JBRadioButton" binding="myUseBundledRadioButton">
+        <constraints>
+          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <selected value="true"/>
+          <text resource-bundle="messages/QuickFixBundle" key="add.library.use.bundled.library.radio.button"/>
+        </properties>
+      </component>
+      <component id="9b5da" class="com.intellij.ui.components.JBRadioButton" binding="myCopyLibraryFilesRadioButton" default-binding="true">
         <constraints>
-          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="2" indent="0" use-parent-layout="false"/>
+          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
         </constraints>
         <properties>
-          <editable value="false"/>
-          <text value=""/>
+          <text resource-bundle="messages/QuickFixBundle" key="add.library.copy.files.to.radio.button"/>
         </properties>
       </component>
+      <vspacer id="aaa28">
+        <constraints>
+          <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+        </constraints>
+      </vspacer>
     </children>
   </grid>
   <buttonGroups>
       <member id="ec66c"/>
       <member id="204d7"/>
     </group>
+    <group name="library_source">
+      <member id="cb577"/>
+    </group>
+    <group name="action">
+      <member id="e9cf2"/>
+      <member id="9b5da"/>
+    </group>
   </buttonGroups>
 </form>
index ebc118e3e6919de721b63e540b222aa235a015b8..dfb26d9ab6b425f4ad4cde16a069c9bd10279542 100644 (file)
@@ -15,8 +15,9 @@
  */
 package com.intellij.codeInsight.daemon.impl.quickfix;
 
+import com.intellij.CommonBundle;
 import com.intellij.codeInsight.daemon.QuickFixBundle;
-import com.intellij.openapi.fileChooser.FileChooserDescriptor;
+import com.intellij.openapi.application.ApplicationNamesInfo;
 import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.project.Project;
@@ -25,70 +26,56 @@ import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.ui.TextFieldWithBrowseButton;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.ui.DocumentAdapter;
-import com.intellij.util.ui.UIUtil;
+import com.intellij.ui.components.JBRadioButton;
 import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 import javax.swing.event.DocumentEvent;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
 public class LocateLibraryDialog extends DialogWrapper {
-  private JPanel contentPane;
-  private JTextPane myDescription;
-  private JLabel myFileLabel;
-  private TextFieldWithBrowseButton myLibraryFile;
-  private JRadioButton myAddThisFileRadioButton;
-  private JRadioButton myCopyToRadioButton;
+  private final List<String> myDefaultLibraryPaths;
+  private JPanel myContentPane;
   private TextFieldWithBrowseButton myCopyToDir;
+  private JBRadioButton myUseBundledRadioButton;
+  private JBRadioButton myCopyLibraryFilesRadioButton;
 
   private final Project myProject;
-  private String myResultingLibraryPath;
+  private List<String> myResultingLibraryPaths;
 
-  public String getResultingLibraryPath() {
-    return myResultingLibraryPath;
-  }
-
-  public LocateLibraryDialog(Module module, String libraryPath, @NonNls final String libraryName, final String libraryDescription ) {
+  public LocateLibraryDialog(@NotNull Module module,
+                             @NotNull List<String> defaultLibraryPaths,
+                             @NotNull @NonNls final String presentableName) {
     super (module.getProject(), true);
-    setTitle ( QuickFixBundle.message("add.library.title.dialog"));
+    myDefaultLibraryPaths = defaultLibraryPaths;
+    setTitle(QuickFixBundle.message("add.library.title.dialog", presentableName));
 
     myProject = module.getProject();
-
-    // copied from Messages.MessageDialog
-    JLabel label = new JLabel();
-    myDescription.setFont(label.getFont());
-    myDescription.setBackground(UIUtil.getOptionPaneBackground());
-    myDescription.setForeground(label.getForeground());
-    myDescription.setText(libraryDescription);
-    // end of copy
-    
-    myFileLabel.setLabelFor(myLibraryFile.getTextField());
-
-    myLibraryFile.setText(new File ( libraryPath, libraryName).getPath() );
-    myLibraryFile.addBrowseFolderListener(QuickFixBundle.message("add.library.title.locate.library"),
-                                          QuickFixBundle.message("add.library.description.locate.library"), myProject,
-                                          new FileChooserDescriptor(false,false,true,false,false,false));
-
-    myCopyToDir.setText(new File (module.getModuleFilePath()).getParent());
+    myUseBundledRadioButton.setText(QuickFixBundle.message("add.library.use.bundled.library.radio.button", presentableName,
+                                                           ApplicationNamesInfo.getInstance().getFullProductName()));
+    myCopyLibraryFilesRadioButton.setText(QuickFixBundle.message("add.library.copy.files.to.radio.button", presentableName));
+    myCopyToDir.setText(new File(new File(module.getModuleFilePath()).getParent(), "lib").getAbsolutePath());
     myCopyToDir.addBrowseFolderListener(QuickFixBundle.message("add.library.title.choose.folder"),
                                         QuickFixBundle.message("add.library.description.choose.folder"), myProject,
                                         FileChooserDescriptorFactory.createSingleFolderDescriptor());
 
-    final ActionListener listener = new ActionListener() {
+    final ItemListener listener = new ItemListener() {
       @Override
-      public void actionPerformed(final ActionEvent e) {
+      public void itemStateChanged(ItemEvent e) {
         updateButtons();
       }
     };
 
-    myAddThisFileRadioButton.addActionListener(listener);
-    myCopyToRadioButton.addActionListener(listener);
-
-    myAddThisFileRadioButton.setSelected(true);
+    myUseBundledRadioButton.addItemListener(listener);
+    myCopyLibraryFilesRadioButton.addItemListener(listener);
 
     myCopyToDir.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
       @Override
@@ -98,69 +85,82 @@ public class LocateLibraryDialog extends DialogWrapper {
     });
 
     updateButtons();
+    init();
+  }
 
-    init ();
+  @NotNull
+  public List<String> showAndGetResult() {
+    return showAndGet() ? getResultingLibraryPaths() : Collections.<String>emptyList();
+  }
+
+  public List<String> getResultingLibraryPaths() {
+    return myResultingLibraryPaths;
   }
 
   private void updateButtons() {
-    final boolean copyEnabled = myCopyToRadioButton.isSelected();
-    myCopyToDir.setEnabled(copyEnabled);
-    if ( copyEnabled ) {
-      myCopyToDir.getTextField().requestFocusInWindow();
-    }
-    setOKActionEnabled(! copyEnabled || !myCopyToDir.getText().isEmpty());
+    final boolean copyFiles = myCopyLibraryFilesRadioButton.isSelected();
+    myCopyToDir.setEnabled(copyFiles);
+    setOKActionEnabled(!copyFiles || !myCopyToDir.getText().isEmpty());
   }
 
   @Override
   @NonNls
   protected String getDimensionServiceKey() {
-    return "#org.jetbrains.codeInsight.daemon.impl.quickfix.LocateLibraryDialog";
+    return "#com.intellij.codeInsight.daemon.impl.quickfix.LocateLibraryDialog";
+  }
+
+  @Nullable
+  @Override
+  public JComponent getPreferredFocusedComponent() {
+    return myUseBundledRadioButton;
   }
 
   @Override
   @Nullable
   protected JComponent createCenterPanel() {
-    return contentPane;
+    return myContentPane;
   }
 
   @Override
   protected void doOKAction() {
     if (getOKAction().isEnabled()) {
-      myResultingLibraryPath = getResultingPath();
-      if ( myResultingLibraryPath != null ) {
+      myResultingLibraryPaths = computeResultingPaths();
+      if (!myResultingLibraryPaths.isEmpty()) {
         close(OK_EXIT_CODE);
       }
     }
   }
 
-  @Nullable
-  private String getResultingPath() {
-    final File srcFile = new File(myLibraryFile.getText());
-    if (!srcFile.exists()) {
-      Messages.showErrorDialog(myProject, QuickFixBundle.message("add.library.error.not.found", srcFile.getPath()),
-                               QuickFixBundle.message("add.library.title.error"));
-      return null;
-    }
-
-    if (!myCopyToRadioButton.isSelected()) {
-      return srcFile.getPath();
+  private List<String> computeResultingPaths() {
+    if (myUseBundledRadioButton.isSelected()) {
+      return myDefaultLibraryPaths;
     }
 
     final String dstDir = myCopyToDir.getText();
     if (dstDir.isEmpty()) {
-      return null;
+      return Collections.emptyList();
     }
-    
-    File dstFile = new File(dstDir, srcFile.getName());
-    try {
-      FileUtil.copy(srcFile, dstFile);
-      return dstFile.getPath();
-    }
-    catch (IOException e) {
-      Messages.showErrorDialog(myProject,
-                               QuickFixBundle.message("add.library.error.cannot.copy", srcFile.getPath(), dstFile.getPath(), e.getMessage()),
-                               QuickFixBundle.message("add.library.title.error"));
-      return null;
+
+    List<String> result = new ArrayList<String>();
+    for (String path : myDefaultLibraryPaths) {
+      final File srcFile = new File(path);
+      if (!srcFile.exists()) {
+        Messages.showErrorDialog(myProject, QuickFixBundle.message("add.library.error.not.found", srcFile.getPath()),
+                                 CommonBundle.getErrorTitle());
+        return Collections.emptyList();
+      }
+      File dstFile = new File(dstDir, srcFile.getName());
+      try {
+        FileUtil.copy(srcFile, dstFile);
+      }
+      catch (IOException e) {
+        Messages.showErrorDialog(myProject,
+                                 QuickFixBundle.message("add.library.error.cannot.copy", srcFile.getPath(), dstFile.getPath(), e.getMessage()),
+                                 CommonBundle.getErrorTitle());
+        return Collections.emptyList();
+      }
+      result.add(FileUtil.toSystemIndependentName(dstFile.getAbsolutePath()));
     }
+    return result;
   }
 }
index c1ac92f24966b4cd942e8ee232ee99cc78332209..5d8eaa2ce240da081fbedfa5d3dd4df65f31da90 100644 (file)
@@ -26,9 +26,7 @@ import com.intellij.codeInsight.daemon.quickFix.MissingDependencyFixProvider;
 import com.intellij.codeInsight.intention.IntentionAction;
 import com.intellij.codeInspection.LocalQuickFix;
 import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.openapi.application.PathManager;
 import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.module.EffectiveLanguageLevelUtil;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.project.DumbService;
 import com.intellij.openapi.project.Project;
@@ -39,7 +37,6 @@ import com.intellij.openapi.vfs.LocalFileSystem;
 import com.intellij.openapi.vfs.VfsUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.packageDependencies.DependencyValidationManager;
-import com.intellij.pom.java.LanguageLevel;
 import com.intellij.psi.*;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.search.PsiShortNamesCache;
@@ -116,7 +113,7 @@ public abstract class OrderEntryFix implements IntentionAction, LocalQuickFix {
     JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
     String fullReferenceText = reference.getCanonicalText();
     for (ExternalLibraryResolver resolver : ExternalLibraryResolver.EP_NAME.getExtensions()) {
-      final ExternalClassResolveResult resolveResult = resolver.resolveClass(shortReferenceName, isReferenceToAnnotation(psiElement));
+      final ExternalClassResolveResult resolveResult = resolver.resolveClass(shortReferenceName, isReferenceToAnnotation(psiElement), currentModule);
       OrderEntryFix fix = null;
       if (resolveResult != null && psiFacade.findClass(resolveResult.getQualifiedClassName(), currentModule.getModuleWithDependenciesAndLibrariesScope(true)) == null) {
         fix = new AddExternalLibraryToDependenciesQuickFix(currentModule, resolveResult.getLibrary(), reference, resolveResult.getQualifiedClassName());
@@ -314,20 +311,11 @@ public abstract class OrderEntryFix implements IntentionAction, LocalQuickFix {
     return VfsUtil.getUrlForLibraryRoot(libraryRoot);
   }
 
-  @Nullable
-  public static String locateAnnotationsJar(@NotNull Module module) {
-    String jarName;
-    String libPath;
-    if (EffectiveLanguageLevelUtil.getEffectiveLanguageLevel(module).isAtLeast(LanguageLevel.JDK_1_8)) {
-      jarName = "annotations-java8.jar";
-      libPath = new File(PathManager.getHomePath(), "redist").getAbsolutePath();
-    }
-    else {
-      jarName = "annotations.jar";
-      libPath = PathManager.getLibPath();
-    }
-    final LocateLibraryDialog dialog = new LocateLibraryDialog(module, libPath, jarName, QuickFixBundle.message("add.library.annotations.description"));
-    return dialog.showAndGet() ? dialog.getResultingLibraryPath() : null;
+  @NotNull
+  public static List<String> locateAnnotationsJars(@NotNull Module module) {
+    List<String> defaultPaths = JetBrainsAnnotationsExternalLibraryResolver.getAnnotationsLibraryDescriptor(module).getLibraryClassesRoots();
+    final LocateLibraryDialog dialog = new LocateLibraryDialog(module, defaultPaths, "JetBrains Annotations");
+    return dialog.showAndGetResult();
   }
 
   public static boolean isAnnotationsJarInPath(Module module) {
index 420020927306514b124a30550ed1895164926476..9b264c1dc744ed81ba35bf12a3c3778f2d6a82d2 100644 (file)
@@ -15,7 +15,6 @@
  */
 package com.intellij.codeInsight.daemon.quickFix;
 
-import com.intellij.openapi.module.Module;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -55,5 +54,5 @@ public abstract class ExternalLibraryDescriptor {
   }
 
   @NotNull
-  public abstract List<String> locateLibraryClassesRoots(@NotNull Module contextModule);
+  public abstract List<String> getLibraryClassesRoots();
 }
index 00f48ff031d22edb8d1d4c064b966f6eaee0c788..253fee1c936e8a7aff5a853428b8203765180041 100644 (file)
@@ -16,6 +16,7 @@
 package com.intellij.codeInsight.daemon.quickFix;
 
 import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.module.Module;
 import com.intellij.util.ThreeState;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -27,7 +28,9 @@ public abstract class ExternalLibraryResolver {
   public static final ExtensionPointName<ExternalLibraryResolver> EP_NAME = ExtensionPointName.create("com.intellij.codeInsight.externalLibraryResolver");
 
   @Nullable
-  public abstract ExternalClassResolveResult resolveClass(@NotNull String shortClassName, @NotNull ThreeState isAnnotation);
+  public abstract ExternalClassResolveResult resolveClass(@NotNull String shortClassName,
+                                                          @NotNull ThreeState isAnnotation,
+                                                          @NotNull Module contextModule);
 
   @Nullable
   public ExternalLibraryDescriptor resolvePackage(@NotNull String packageName) {
index 4f5cc2d43ff8d3b76b2ee023615e5dd7a3be4b08..80a7ac76343c93ed63cb548a640eaa14c0ca98ee 100644 (file)
@@ -35,7 +35,7 @@ public class JCiPExternalLibraryResolver extends ExternalLibraryResolver {
     new ExternalLibraryDescriptor("net.jcip", "jcip-annotations", null) {
       @NotNull
       @Override
-      public List<String> locateLibraryClassesRoots(@NotNull Module contextModule) {
+      public List<String> getLibraryClassesRoots() {
         return Collections.singletonList(PathUtil.getJarPathForClass(GuardedBy.class));
       }
 
@@ -47,7 +47,7 @@ public class JCiPExternalLibraryResolver extends ExternalLibraryResolver {
 
   @Nullable
   @Override
-  public ExternalClassResolveResult resolveClass(@NotNull String shortClassName, @NotNull ThreeState isAnnotation) {
+  public ExternalClassResolveResult resolveClass(@NotNull String shortClassName, @NotNull ThreeState isAnnotation, @NotNull Module contextModule) {
     if (JCiPUtil.isJCiPAnnotation(shortClassName) && isAnnotation == ThreeState.YES) {
       return new ExternalClassResolveResult("net.jcip.annotations." + shortClassName, JDCIP_LIBRARY_DESCRIPTOR);
     }
index 19d8af3a6c41e6624329fc0adae27876674745a5..9e0ce12298e16c3e0bd98249a28870f569755c4b 100644 (file)
@@ -179,13 +179,13 @@ public class InferNullityAnnotationsAction extends BaseAnalysisAction {
                                              "It is possible to configure custom JAR\nin e.g. Constant Conditions & Exceptions inspection or use JetBrains annotations available in installation. " +
                                              "\nIntelliJ IDEA nullity annotations are freely usable and redistributable under the Apache 2.0 license.\nWould you like to do it now?",
                                     title, Messages.getErrorIcon()) == Messages.OK) {
-      final String path = OrderEntryFix.locateAnnotationsJar(modulesWithoutAnnotations.iterator().next());
-      if (path != null) {
+      final List<String> paths = OrderEntryFix.locateAnnotationsJars(modulesWithoutAnnotations.iterator().next());
+      if (!paths.isEmpty()) {
         new WriteCommandAction(project) {
           @Override
           protected void run(@NotNull final Result result) throws Throwable {
             for (Module module : modulesWithoutAnnotations) {
-              OrderEntryFix.addJarsToRoots(Collections.singletonList(path), null, module, null);
+              OrderEntryFix.addJarsToRoots(paths, null, module, null);
             }
           }
         }.execute();
index 7c21ac2889cc9df7023ca912ba6a71414c6bf0d6..5375cb726f21c608d3ea75766aab956e6210ad12 100644 (file)
@@ -42,7 +42,7 @@ public class JUnitExternalLibraryResolver extends ExternalLibraryResolver {
     return new ExternalLibraryDescriptor("junit", "junit", version) {
       @NotNull
       @Override
-      public List<String> locateLibraryClassesRoots(@NotNull Module contextModule) {
+      public List<String> getLibraryClassesRoots() {
         return TestFramework.EXTENSION_NAME.findExtension(frameworkClass).getLibraryPaths();
       }
 
@@ -58,7 +58,7 @@ public class JUnitExternalLibraryResolver extends ExternalLibraryResolver {
   );
   @Nullable
   @Override
-  public ExternalClassResolveResult resolveClass(@NotNull String shortClassName, @NotNull ThreeState isAnnotation) {
+  public ExternalClassResolveResult resolveClass(@NotNull String shortClassName, @NotNull ThreeState isAnnotation, @NotNull Module contextModule) {
     if ("TestCase".equals(shortClassName)) {
       return new ExternalClassResolveResult("junit.framework.TestCase", JUNIT3);
     }
index 211b64d7b77a19a8f68bfa531a1aedb807b2a544..2a9f198efdea7310d6314a2dcc73f1ebd3c0eba5 100644 (file)
@@ -40,14 +40,14 @@ public class TestNGExternalLibraryResolver extends ExternalLibraryResolver {
   private static final ExternalLibraryDescriptor TESTNG_DESCRIPTOR = new ExternalLibraryDescriptor("org.testng", "testng", null) {
     @NotNull
     @Override
-    public List<String> locateLibraryClassesRoots(@NotNull Module contextModule) {
+    public List<String> getLibraryClassesRoots() {
       return Collections.singletonList(PathUtil.getJarPathForClass(Test.class));
     }
   };
 
   @Nullable
   @Override
-  public ExternalClassResolveResult resolveClass(@NotNull String shortClassName, @NotNull ThreeState isAnnotation) {
+  public ExternalClassResolveResult resolveClass(@NotNull String shortClassName, @NotNull ThreeState isAnnotation, @NotNull Module contextModule) {
     if (TEST_NG_ANNOTATIONS.contains(shortClassName)) {
       return new ExternalClassResolveResult("org.testng.annotations." + shortClassName, TESTNG_DESCRIPTOR);
     }
index fd07073160dd4655f5b479d37bf14f19ca18446d..a61a5eaff41e958077b37bd5a3e99d3b3237ffe0 100644 (file)
@@ -224,19 +224,14 @@ orderEntry.fix.title.circular.dependency.warning=Circular Dependency Warning
 static.import.method.text=Static import method
 static.import.method.choose.method.to.import=Choose Method to Import
 
-add.library.title.dialog=Add Library to Project
-add.library.title.locate.library=Locate Library
-add.library.description.locate.library=Locate library file which will be added as module library
+add.library.title.dialog=Add ''{0}'' Library to Project
 add.library.title.choose.folder=Choose Directory
 add.library.description.choose.folder=Choose directory where the library will be copied
-add.library.title.error=Error
 add.library.error.not.found=Library file ''{0}'' does not exist
 add.library.error.cannot.copy=Cannot copy ''{0}'' to ''{1}''\n({2})
-add.library.annotations.description=You are using annotation classes from org.jetbrains.annotations package.\n\
-Please add ''annotations.jar'' library to your project.
-add.library.file=Library &file:
-add.library.add.this=&Add this file
-add.library.copy.to=&Copy to
+add.library.use.bundled.library.radio.button=&Use ''{0}'' from {1} distribution
+add.library.copy.files.to.radio.button=&Copy ''{0}'' library files to
+
 permute.arguments=Permute arguments
 fix.single.character.string.to.char.literal.text=Change {0} to {1} (to {2} literal)
 fix.single.character.string.to.char.literal.family=Fix literal type