junit 5 tags support (IDEA-163481)
[idea/community.git] / plugins / junit / src / com / intellij / execution / junit2 / configuration / JUnitConfigurable.java
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.intellij.execution.junit2.configuration;
18
19 import com.intellij.application.options.ModuleDescriptionsComboBox;
20 import com.intellij.execution.ExecutionBundle;
21 import com.intellij.execution.MethodBrowser;
22 import com.intellij.execution.ShortenCommandLine;
23 import com.intellij.execution.configuration.BrowseModuleValueActionListener;
24 import com.intellij.execution.junit.JUnitConfiguration;
25 import com.intellij.execution.junit.JUnitConfigurationType;
26 import com.intellij.execution.junit.JUnitUtil;
27 import com.intellij.execution.junit.TestClassFilter;
28 import com.intellij.execution.testframework.SourceScope;
29 import com.intellij.execution.testframework.TestSearchScope;
30 import com.intellij.execution.ui.*;
31 import com.intellij.ide.util.ClassFilter;
32 import com.intellij.ide.util.PackageChooserDialog;
33 import com.intellij.openapi.fileChooser.FileChooser;
34 import com.intellij.openapi.fileChooser.FileChooserDescriptor;
35 import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
36 import com.intellij.openapi.fileChooser.FileChooserFactory;
37 import com.intellij.openapi.fileTypes.PlainTextLanguage;
38 import com.intellij.openapi.module.Module;
39 import com.intellij.openapi.options.SettingsEditor;
40 import com.intellij.openapi.project.Project;
41 import com.intellij.openapi.ui.ComponentWithBrowseButton;
42 import com.intellij.openapi.ui.LabeledComponent;
43 import com.intellij.openapi.ui.TextFieldWithBrowseButton;
44 import com.intellij.openapi.ui.ex.MessagesEx;
45 import com.intellij.openapi.util.Condition;
46 import com.intellij.openapi.util.io.FileUtil;
47 import com.intellij.openapi.util.registry.Registry;
48 import com.intellij.openapi.util.text.StringUtil;
49 import com.intellij.openapi.vcs.changes.ChangeListManager;
50 import com.intellij.openapi.vcs.changes.LocalChangeList;
51 import com.intellij.openapi.vfs.VirtualFile;
52 import com.intellij.psi.*;
53 import com.intellij.psi.search.GlobalSearchScope;
54 import com.intellij.rt.execution.junit.RepeatCount;
55 import com.intellij.ui.*;
56 import com.intellij.ui.components.JBLabel;
57 import com.intellij.ui.components.fields.ExpandableTextField;
58 import com.intellij.util.IconUtil;
59 import com.intellij.util.ui.UIUtil;
60 import gnu.trove.TIntArrayList;
61 import org.jetbrains.annotations.NotNull;
62
63 import javax.swing.*;
64 import javax.swing.event.ChangeEvent;
65 import javax.swing.event.ChangeListener;
66 import javax.swing.text.Document;
67 import javax.swing.text.PlainDocument;
68 import java.awt.*;
69 import java.awt.event.ActionEvent;
70 import java.awt.event.ActionListener;
71 import java.util.Arrays;
72 import java.util.List;
73
74 public class JUnitConfigurable<T extends JUnitConfiguration> extends SettingsEditor<T> implements PanelWithAnchor {
75   private static final List<TIntArrayList> ourEnabledFields = Arrays.asList(
76     new TIntArrayList(new int[]{0}),
77     new TIntArrayList(new int[]{1}),
78     new TIntArrayList(new int[]{1, 2}),
79     new TIntArrayList(new int[]{3}),
80     new TIntArrayList(new int[]{4}),
81     new TIntArrayList(new int[]{5}),
82     new TIntArrayList(new int[]{1, 2}),
83     new TIntArrayList(new int[]{6})
84     );
85   private static final String[] FORK_MODE_ALL =
86     {JUnitConfiguration.FORK_NONE, JUnitConfiguration.FORK_METHOD, JUnitConfiguration.FORK_KLASS};
87   private static final String[] FORK_MODE = {JUnitConfiguration.FORK_NONE, JUnitConfiguration.FORK_METHOD};
88   private final ConfigurationModuleSelector myModuleSelector;
89   private final LabeledComponent[] myTestLocations = new LabeledComponent[6];
90   private final JUnitConfigurationModel myModel;
91   private final BrowseModuleValueActionListener[] myBrowsers;
92   private JComponent myPackagePanel;
93   private LabeledComponent<EditorTextFieldWithBrowseButton> myPackage;
94   private LabeledComponent<TextFieldWithBrowseButton> myDir;
95   private LabeledComponent<JPanel> myPattern;
96   private LabeledComponent<EditorTextFieldWithBrowseButton> myClass;
97   private LabeledComponent<EditorTextFieldWithBrowseButton> myMethod;
98   private LabeledComponent<EditorTextFieldWithBrowseButton> myCategory;
99   // Fields
100   private JPanel myWholePanel;
101   private LabeledComponent<ModuleDescriptionsComboBox> myModule;
102   private CommonJavaParametersPanel myCommonJavaParameters;
103   private JRadioButton myWholeProjectScope;
104   private JRadioButton mySingleModuleScope;
105   private JRadioButton myModuleWDScope;
106   private TextFieldWithBrowseButton myPatternTextField;
107   private JrePathEditor myJrePathEditor;
108   private LabeledComponent<ShortenCommandLineModeCombo> myShortenClasspathModeCombo;
109   private JComboBox myForkCb;
110   private JBLabel myTestLabel;
111   private JComboBox myTypeChooser;
112   private JBLabel mySearchForTestsLabel;
113   private JPanel myScopesPanel;
114   private JComboBox myRepeatCb;
115   private JTextField myRepeatCountField;
116   private LabeledComponent<JComboBox<String>> myChangeListLabeledComponent;
117   private LabeledComponent<RawCommandLineEditor> myUniqueIdField;
118   private LabeledComponent<RawCommandLineEditor> myTagsField;
119   private Project myProject;
120   private JComponent anchor;
121
122   public JUnitConfigurable(final Project project) {
123     myProject = project;
124     myModel = new JUnitConfigurationModel(project);
125     myModuleSelector = new ConfigurationModuleSelector(project, getModulesComponent());
126     myJrePathEditor.setDefaultJreSelector(DefaultJreSelector.fromModuleDependencies(getModulesComponent(), false));
127     myCommonJavaParameters.setModuleContext(myModuleSelector.getModule());
128     myCommonJavaParameters.setHasModuleMacro();
129     myModule.getComponent().addActionListener(new ActionListener() {
130       public void actionPerformed(ActionEvent e) {
131         myCommonJavaParameters.setModuleContext(myModuleSelector.getModule());
132       }
133     });
134     myBrowsers = new BrowseModuleValueActionListener[]{
135       new PackageChooserActionListener(project),
136       new TestClassBrowser(project),
137       new MethodBrowser(project) {
138         protected Condition<PsiMethod> getFilter(PsiClass testClass) {
139           return new JUnitUtil.TestMethodFilter(testClass);
140         }
141
142         @Override
143         protected String getClassName() {
144           return JUnitConfigurable.this.getClassName();
145         }
146
147         @Override
148         protected ConfigurationModuleSelector getModuleSelector() {
149           return myModuleSelector;
150         }
151       },
152       new TestsChooserActionListener(project),
153       new BrowseModuleValueActionListener(project) {
154         @Override
155         protected String showDialog() {
156           final VirtualFile virtualFile =
157             FileChooser.chooseFile(FileChooserDescriptorFactory.createSingleFolderDescriptor(), project, null);
158           if (virtualFile != null) {
159             return FileUtil.toSystemDependentName(virtualFile.getPath());
160           }
161           return null;
162         }
163       },
164       new CategoryBrowser(project),
165       null
166     };
167     // Garbage support
168     final DefaultComboBoxModel aModel = new DefaultComboBoxModel();
169     aModel.addElement(JUnitConfigurationModel.ALL_IN_PACKAGE);
170     aModel.addElement(JUnitConfigurationModel.DIR);
171     aModel.addElement(JUnitConfigurationModel.PATTERN);
172     aModel.addElement(JUnitConfigurationModel.CLASS);
173     aModel.addElement(JUnitConfigurationModel.METHOD);
174     aModel.addElement(JUnitConfigurationModel.CATEGORY);
175     aModel.addElement(JUnitConfigurationModel.UNIQUE_ID);
176     aModel.addElement(JUnitConfigurationModel.TAGS);
177     if (Registry.is("testDiscovery.enabled")) {
178       aModel.addElement(JUnitConfigurationModel.BY_SOURCE_POSITION);
179       aModel.addElement(JUnitConfigurationModel.BY_SOURCE_CHANGES);
180     }
181     myTypeChooser.setModel(aModel);
182     myTypeChooser.setRenderer(new ListCellRendererWrapper<Integer>() {
183       @Override
184       public void customize(JList list, Integer value, int index, boolean selected, boolean hasFocus) {
185         switch (value) {
186           case JUnitConfigurationModel.ALL_IN_PACKAGE:
187             setText("All in package");
188             break;
189           case JUnitConfigurationModel.DIR:
190             setText("All in directory");
191             break;
192           case JUnitConfigurationModel.PATTERN:
193             setText("Pattern");
194             break;
195           case JUnitConfigurationModel.CLASS:
196             setText("Class");
197             break;
198           case JUnitConfigurationModel.METHOD:
199             setText("Method");
200             break;
201           case JUnitConfigurationModel.CATEGORY:
202             setText("Category");
203             break;
204           case JUnitConfigurationModel.UNIQUE_ID:
205             setText("UniqueId");
206             break;
207           case JUnitConfigurationModel.TAGS:
208             setText("Tags (JUnit 5)");
209             break;
210           case JUnitConfigurationModel.BY_SOURCE_POSITION:
211             setText("Through source location");
212             break;
213           case JUnitConfigurationModel.BY_SOURCE_CHANGES:
214             setText("Over changes in sources");
215             break;
216         }
217       }
218     });
219
220     myTestLocations[JUnitConfigurationModel.ALL_IN_PACKAGE] = myPackage;
221     myTestLocations[JUnitConfigurationModel.CLASS] = myClass;
222     myTestLocations[JUnitConfigurationModel.METHOD] = myMethod;
223     myTestLocations[JUnitConfigurationModel.DIR] = myDir;
224     myTestLocations[JUnitConfigurationModel.CATEGORY] = myCategory;
225
226     myRepeatCb.setModel(new DefaultComboBoxModel(RepeatCount.REPEAT_TYPES));
227     myRepeatCb.setSelectedItem(RepeatCount.ONCE);
228     myRepeatCb.addActionListener(new ActionListener() {
229       @Override
230       public void actionPerformed(ActionEvent e) {
231         myRepeatCountField.setEnabled(RepeatCount.N.equals(myRepeatCb.getSelectedItem()));
232       }
233     });
234
235     final JPanel panel = myPattern.getComponent();
236     panel.setLayout(new BorderLayout());
237     myPatternTextField = new TextFieldWithBrowseButton(new ExpandableTextField());
238     myPatternTextField.setButtonIcon(IconUtil.getAddIcon());
239     panel.add(myPatternTextField, BorderLayout.CENTER);
240     myTestLocations[JUnitConfigurationModel.PATTERN] = myPattern;
241
242     final FileChooserDescriptor dirFileChooser = FileChooserDescriptorFactory.createSingleFolderDescriptor();
243     dirFileChooser.setHideIgnored(false);
244     final JTextField textField = myDir.getComponent().getTextField();
245     InsertPathAction.addTo(textField, dirFileChooser);
246     FileChooserFactory.getInstance().installFileCompletion(textField, dirFileChooser, true, null);
247     // Done
248
249     myModel.setListener(this);
250
251     myTypeChooser.addActionListener(new ActionListener() {
252       @Override
253       public void actionPerformed(ActionEvent e) {
254         final Object selectedItem = myTypeChooser.getSelectedItem();
255         myModel.setType((Integer)selectedItem);
256         changePanel();
257       }
258     }
259     );
260
261     myRepeatCb.addActionListener(new ActionListener() {
262       @Override
263       public void actionPerformed(ActionEvent e) {
264         if ((Integer) myTypeChooser.getSelectedItem() == JUnitConfigurationModel.CLASS) {
265           myForkCb.setModel(getForkModelBasedOnRepeat());
266         }
267       }
268     });
269     myModel.setType(JUnitConfigurationModel.CLASS);
270     installDocuments();
271     addRadioButtonsListeners(new JRadioButton[]{myWholeProjectScope, mySingleModuleScope, myModuleWDScope}, null);
272     myWholeProjectScope.addChangeListener(new ChangeListener() {
273       public void stateChanged(final ChangeEvent e) {
274         onScopeChanged();
275       }
276     });
277
278     UIUtil.setEnabled(myCommonJavaParameters.getProgramParametersComponent(), false, true);
279
280     setAnchor(mySearchForTestsLabel);
281     myJrePathEditor.setAnchor(myModule.getLabel());
282     myCommonJavaParameters.setAnchor(myModule.getLabel());
283     myShortenClasspathModeCombo.setAnchor(myModule.getLabel());
284
285     final DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();
286     myChangeListLabeledComponent.getComponent().setModel(model);
287     model.addElement("All");
288
289     final List<LocalChangeList> changeLists = ChangeListManager.getInstance(project).getChangeLists();
290     for (LocalChangeList changeList : changeLists) {
291       model.addElement(changeList.getName());
292     }
293
294     myShortenClasspathModeCombo.setComponent(new ShortenCommandLineModeCombo(myProject, myJrePathEditor, myModule.getComponent()));
295   }
296
297   private static void addRadioButtonsListeners(final JRadioButton[] radioButtons, ChangeListener listener) {
298     final ButtonGroup group = new ButtonGroup();
299     for (final JRadioButton radioButton : radioButtons) {
300       radioButton.getModel().addChangeListener(listener);
301       group.add(radioButton);
302     }
303     if (group.getSelection() == null) group.setSelected(radioButtons[0].getModel(), true);
304   }
305
306   public void applyEditorTo(@NotNull final JUnitConfiguration configuration) {
307     configuration.setRepeatMode((String)myRepeatCb.getSelectedItem());
308     try {
309       configuration.setRepeatCount(Integer.parseInt(myRepeatCountField.getText()));
310     }
311     catch (NumberFormatException e) {
312       configuration.setRepeatCount(1);
313     }
314     configuration.getPersistentData().setUniqueIds(myUniqueIdField.getComponent().getText().split(" "));
315     configuration.getPersistentData().setTags(myTagsField.getComponent().getText().split(" "));
316     configuration.getPersistentData().setChangeList((String)myChangeListLabeledComponent.getComponent().getSelectedItem());
317     myModel.apply(getModuleSelector().getModule(), configuration);
318     applyHelpersTo(configuration);
319     final JUnitConfiguration.Data data = configuration.getPersistentData();
320     if (myWholeProjectScope.isSelected()) {
321       data.setScope(TestSearchScope.WHOLE_PROJECT);
322     }
323     else if (mySingleModuleScope.isSelected()) {
324       data.setScope(TestSearchScope.SINGLE_MODULE);
325     }
326     else if (myModuleWDScope.isSelected()) {
327       data.setScope(TestSearchScope.MODULE_WITH_DEPENDENCIES);
328     }
329     configuration.setAlternativeJrePath(myJrePathEditor.getJrePathOrName());
330     configuration.setAlternativeJrePathEnabled(myJrePathEditor.isAlternativeJreSelected());
331
332     myCommonJavaParameters.applyTo(configuration);
333     configuration.setForkMode((String)myForkCb.getSelectedItem());
334     configuration.setShortenCommandLine((ShortenCommandLine)myShortenClasspathModeCombo.getComponent().getSelectedItem());
335   }
336
337   public void resetEditorFrom(@NotNull final JUnitConfiguration configuration) {
338     final int count = configuration.getRepeatCount();
339     myRepeatCountField.setText(String.valueOf(count));
340     myRepeatCountField.setEnabled(count > 1);
341     myRepeatCb.setSelectedItem(configuration.getRepeatMode());
342
343     myModel.reset(configuration);
344     myChangeListLabeledComponent.getComponent().setSelectedItem(configuration.getPersistentData().getChangeList());
345     String[] ids = configuration.getPersistentData().getUniqueIds();
346     myUniqueIdField.getComponent().setText(ids != null ? StringUtil.join(ids, " ") : null);
347
348     String[] tags = configuration.getPersistentData().getTags();
349     myTagsField.getComponent().setText(tags != null ? StringUtil.join(tags, " ") : null);
350
351     myCommonJavaParameters.reset(configuration);
352     getModuleSelector().reset(configuration);
353     final TestSearchScope scope = configuration.getPersistentData().getScope();
354     if (scope == TestSearchScope.SINGLE_MODULE) {
355       mySingleModuleScope.setSelected(true);
356     }
357     else if (scope == TestSearchScope.MODULE_WITH_DEPENDENCIES) {
358       myModuleWDScope.setSelected(true);
359     }
360     else {
361       myWholeProjectScope.setSelected(true);
362     }
363     myJrePathEditor
364       .setPathOrName(configuration.getAlternativeJrePath(), configuration.isAlternativeJrePathEnabled());
365     myForkCb.setSelectedItem(configuration.getForkMode());
366     myShortenClasspathModeCombo.getComponent().setSelectedItem(configuration.getShortenCommandLine());
367   }
368
369   private void changePanel () {
370     String selectedItem = (String)myForkCb.getSelectedItem();
371     if (selectedItem == null) {
372       selectedItem = JUnitConfiguration.FORK_NONE;
373     }
374     final Integer selectedType = (Integer)myTypeChooser.getSelectedItem();
375     if (selectedType == JUnitConfigurationModel.ALL_IN_PACKAGE) {
376       myPackagePanel.setVisible(true);
377       myScopesPanel.setVisible(true);
378       myPattern.setVisible(false);
379       myClass.setVisible(false);
380       myCategory.setVisible(false);
381       myUniqueIdField.setVisible(false);
382       myTagsField.setVisible(false);
383       myMethod.setVisible(false);
384       myDir.setVisible(false);
385       myChangeListLabeledComponent.setVisible(false);
386       myForkCb.setEnabled(true);
387       myForkCb.setModel(new DefaultComboBoxModel(FORK_MODE_ALL));
388       myForkCb.setSelectedItem(selectedItem);
389     } else if (selectedType == JUnitConfigurationModel.DIR) {
390       myPackagePanel.setVisible(false);
391       myScopesPanel.setVisible(false);
392       myDir.setVisible(true);
393       myPattern.setVisible(false);
394       myClass.setVisible(false);
395       myCategory.setVisible(false);
396       myUniqueIdField.setVisible(false);
397       myTagsField.setVisible(false);
398       myChangeListLabeledComponent.setVisible(false);
399       myMethod.setVisible(false);
400       myForkCb.setEnabled(true);
401       myForkCb.setModel(new DefaultComboBoxModel(FORK_MODE_ALL));
402       myForkCb.setSelectedItem(selectedItem);
403     }
404     else if (selectedType == JUnitConfigurationModel.CLASS) {
405       myPackagePanel.setVisible(false);
406       myScopesPanel.setVisible(false);
407       myPattern.setVisible(false);
408       myDir.setVisible(false);
409       myClass.setVisible(true);
410       myCategory.setVisible(false);
411       myUniqueIdField.setVisible(false);
412       myTagsField.setVisible(false);
413       myChangeListLabeledComponent.setVisible(false);
414       myMethod.setVisible(false);
415       myForkCb.setEnabled(true);
416       myForkCb.setModel(getForkModelBasedOnRepeat());
417       myForkCb.setSelectedItem(selectedItem != JUnitConfiguration.FORK_KLASS ? selectedItem : JUnitConfiguration.FORK_METHOD);
418     }
419     else if (selectedType == JUnitConfigurationModel.METHOD || selectedType == JUnitConfigurationModel.BY_SOURCE_POSITION){
420       myPackagePanel.setVisible(false);
421       myScopesPanel.setVisible(false);
422       myPattern.setVisible(false);
423       myDir.setVisible(false);
424       myClass.setVisible(true);
425       myCategory.setVisible(false);
426       myUniqueIdField.setVisible(false);
427       myTagsField.setVisible(false);
428       myMethod.setVisible(true);
429       myChangeListLabeledComponent.setVisible(false);
430       myForkCb.setEnabled(false);
431       myForkCb.setSelectedItem(JUnitConfiguration.FORK_NONE);
432     } else if (selectedType == JUnitConfigurationModel.CATEGORY) {
433       myPackagePanel.setVisible(false);
434       myScopesPanel.setVisible(true);
435       myDir.setVisible(false);
436       myPattern.setVisible(false);
437       myClass.setVisible(false);
438       myCategory.setVisible(true);
439       myUniqueIdField.setVisible(false);
440       myTagsField.setVisible(false);
441       myMethod.setVisible(false);
442       myChangeListLabeledComponent.setVisible(false);
443       myForkCb.setEnabled(true);
444       myForkCb.setModel(new DefaultComboBoxModel(FORK_MODE_ALL));
445       myForkCb.setSelectedItem(selectedItem);
446     }
447     else if (selectedType == JUnitConfigurationModel.BY_SOURCE_CHANGES) {
448       myPackagePanel.setVisible(false);
449       myScopesPanel.setVisible(false);
450       myDir.setVisible(false);
451       myPattern.setVisible(false);
452       myClass.setVisible(false);
453       myCategory.setVisible(false);
454       myUniqueIdField.setVisible(false);
455       myTagsField.setVisible(false);
456       myMethod.setVisible(false);
457       myChangeListLabeledComponent.setVisible(true);
458       myForkCb.setEnabled(true);
459       myForkCb.setModel(new DefaultComboBoxModel(FORK_MODE_ALL));
460       myForkCb.setSelectedItem(selectedItem);
461     }
462     else if (selectedType == JUnitConfigurationModel.UNIQUE_ID) {
463       myPackagePanel.setVisible(false);
464       myScopesPanel.setVisible(false);
465       myDir.setVisible(false);
466       myPattern.setVisible(false);
467       myClass.setVisible(false);
468       myCategory.setVisible(false);
469       myUniqueIdField.setVisible(true);
470       myTagsField.setVisible(false);
471       myMethod.setVisible(false);
472       myChangeListLabeledComponent.setVisible(false);
473       myForkCb.setEnabled(true);
474       myForkCb.setModel(new DefaultComboBoxModel(FORK_MODE_ALL));
475       myForkCb.setSelectedItem(selectedItem);
476     }
477     else if (selectedType == JUnitConfigurationModel.TAGS) {
478       myPackagePanel.setVisible(false);
479       myScopesPanel.setVisible(false);
480       myDir.setVisible(false);
481       myPattern.setVisible(false);
482       myClass.setVisible(false);
483       myCategory.setVisible(false);
484       myUniqueIdField.setVisible(false);
485       myTagsField.setVisible(true);
486       myMethod.setVisible(false);
487       myChangeListLabeledComponent.setVisible(false);
488       myForkCb.setEnabled(true);
489       myForkCb.setModel(new DefaultComboBoxModel(FORK_MODE_ALL));
490       myForkCb.setSelectedItem(selectedItem);
491     }
492     else {
493       myPackagePanel.setVisible(false);
494       myScopesPanel.setVisible(true);
495       myPattern.setVisible(true);
496       myDir.setVisible(false);
497       myClass.setVisible(false);
498       myCategory.setVisible(false);
499       myUniqueIdField.setVisible(false);
500       myTagsField.setVisible(false);
501       myMethod.setVisible(true);
502       myChangeListLabeledComponent.setVisible(false);
503       myForkCb.setEnabled(true);
504       myForkCb.setModel(new DefaultComboBoxModel(FORK_MODE_ALL));
505       myForkCb.setSelectedItem(selectedItem);
506     }
507   }
508
509   private DefaultComboBoxModel getForkModelBasedOnRepeat() {
510     return new DefaultComboBoxModel(RepeatCount.ONCE.equals(myRepeatCb.getSelectedItem()) ? FORK_MODE : FORK_MODE_ALL);
511   }
512
513   public ModuleDescriptionsComboBox getModulesComponent() {
514     return myModule.getComponent();
515   }
516
517   public ConfigurationModuleSelector getModuleSelector() {
518     return myModuleSelector;
519   }
520
521   private void installDocuments() {
522     for (int i = 0; i < myTestLocations.length; i++) {
523       final LabeledComponent testLocation = getTestLocation(i);
524       final JComponent component = testLocation.getComponent();
525       final ComponentWithBrowseButton field;
526       Object document;
527       if (component instanceof TextFieldWithBrowseButton) {
528         field = (TextFieldWithBrowseButton)component;
529         document = new PlainDocument();
530         ((TextFieldWithBrowseButton)field).getTextField().setDocument((Document)document);
531       } else if (component instanceof EditorTextFieldWithBrowseButton) {
532         field = (ComponentWithBrowseButton)component;
533         document = ((EditorTextField)field.getChildComponent()).getDocument();
534       }
535       else {
536         field = myPatternTextField;
537         document = new PlainDocument();
538         ((TextFieldWithBrowseButton)field).getTextField().setDocument((Document)document);
539         
540       }
541       myBrowsers[i].setField(field);
542       if (myBrowsers[i] instanceof MethodBrowser) {
543         final EditorTextField childComponent = (EditorTextField)field.getChildComponent();
544         ((MethodBrowser)myBrowsers[i]).installCompletion(childComponent);
545         document = childComponent.getDocument();
546       }
547       myModel.setJUnitDocument(i, document);
548     }
549   }
550
551   public LabeledComponent getTestLocation(final int index) {
552     return myTestLocations[index];
553   }
554
555   private void createUIComponents() {
556     myPackage = new LabeledComponent<>();
557     myPackage.setComponent(new EditorTextFieldWithBrowseButton(myProject, false));
558
559     myClass = new LabeledComponent<>();
560     final TestClassBrowser classBrowser = new TestClassBrowser(myProject);
561     myClass.setComponent(new EditorTextFieldWithBrowseButton(myProject, true, new JavaCodeFragment.VisibilityChecker() {
562       @Override
563       public Visibility isDeclarationVisible(PsiElement declaration, PsiElement place) {
564         try {
565           if (declaration instanceof PsiClass && (classBrowser.getFilter().isAccepted(((PsiClass)declaration)) || classBrowser.findClass(((PsiClass)declaration).getQualifiedName()) != null && place.getParent() != null)) {
566             return Visibility.VISIBLE;
567           }
568         }
569         catch (ClassBrowser.NoFilterException e) {
570           return Visibility.NOT_VISIBLE;
571         }
572         return Visibility.NOT_VISIBLE;
573       }
574     }));
575
576     myCategory = new LabeledComponent<>();
577     myCategory.setComponent(new EditorTextFieldWithBrowseButton(myProject, true, new JavaCodeFragment.VisibilityChecker() {
578       @Override
579       public Visibility isDeclarationVisible(PsiElement declaration, PsiElement place) {
580         if (declaration instanceof PsiClass) {
581           return Visibility.VISIBLE;
582         }
583         return Visibility.NOT_VISIBLE;
584       }
585     }));
586
587     myMethod = new LabeledComponent<>();
588     final EditorTextFieldWithBrowseButton textFieldWithBrowseButton = new EditorTextFieldWithBrowseButton(myProject, true,
589                                                                                                           JavaCodeFragment.VisibilityChecker.EVERYTHING_VISIBLE,
590                                                                                                           PlainTextLanguage.INSTANCE.getAssociatedFileType());
591     myMethod.setComponent(textFieldWithBrowseButton);
592
593     myShortenClasspathModeCombo = new LabeledComponent<>();
594   }
595
596   @Override
597   public JComponent getAnchor() {
598     return anchor;
599   }
600
601   @Override
602   public void setAnchor(JComponent anchor) {
603     this.anchor = anchor;
604     mySearchForTestsLabel.setAnchor(anchor);
605     myTestLabel.setAnchor(anchor);
606     myClass.setAnchor(anchor);
607     myDir.setAnchor(anchor);
608     myMethod.setAnchor(anchor);
609     myPattern.setAnchor(anchor);
610     myPackage.setAnchor(anchor);
611     myCategory.setAnchor(anchor);
612     myUniqueIdField.setAnchor(anchor);
613     myTagsField.setAnchor(anchor);
614     myChangeListLabeledComponent.setAnchor(anchor);
615   }
616
617   public void onTypeChanged(final int newType) {
618     myTypeChooser.setSelectedItem(newType);
619     final TIntArrayList enabledFields = ourEnabledFields.get(newType);
620     for (int i = 0; i < myTestLocations.length; i++)
621       getTestLocation(i).setEnabled(enabledFields.contains(i));
622     /*if (newType == JUnitConfigurationModel.PATTERN) {
623       myModule.setEnabled(false);
624     } else */if (newType != JUnitConfigurationModel.ALL_IN_PACKAGE &&
625                  newType != JUnitConfigurationModel.PATTERN &&
626                  newType != JUnitConfigurationModel.CATEGORY &&
627                  newType != JUnitConfigurationModel.TAGS &&
628                  newType != JUnitConfigurationModel.UNIQUE_ID) {
629       myModule.setEnabled(true);
630     }
631     else {
632       onScopeChanged();
633     }
634   }
635
636   private void onScopeChanged() {
637     final Integer selectedItem = (Integer)myTypeChooser.getSelectedItem();
638     final boolean allInPackageAllInProject = (selectedItem == JUnitConfigurationModel.ALL_IN_PACKAGE ||
639                                               selectedItem == JUnitConfigurationModel.PATTERN ||
640                                               selectedItem == JUnitConfigurationModel.CATEGORY ||
641                                               selectedItem == JUnitConfigurationModel.TAGS ||
642                                               selectedItem == JUnitConfigurationModel.UNIQUE_ID ) && myWholeProjectScope.isSelected();
643     myModule.setEnabled(!allInPackageAllInProject);
644     if (allInPackageAllInProject) {
645       myModule.getComponent().setSelectedItem(null);
646     }
647   }
648
649   private String getClassName() {
650     return ((LabeledComponent<EditorTextFieldWithBrowseButton>)getTestLocation(JUnitConfigurationModel.CLASS)).getComponent().getText();
651   }
652
653   private void setPackage(final PsiPackage aPackage) {
654     if (aPackage == null) return;
655     ((LabeledComponent<EditorTextFieldWithBrowseButton>)getTestLocation(JUnitConfigurationModel.ALL_IN_PACKAGE)).getComponent()
656       .setText(aPackage.getQualifiedName());
657   }
658
659   @NotNull
660   public JComponent createEditor() {
661     return myWholePanel;
662   }
663
664   private void applyHelpersTo(final JUnitConfiguration currentState) {
665     myCommonJavaParameters.applyTo(currentState);
666     getModuleSelector().applyTo(currentState);
667   }
668
669   private static class PackageChooserActionListener extends BrowseModuleValueActionListener {
670     public PackageChooserActionListener(final Project project) {
671       super(project);
672     }
673
674     protected String showDialog() {
675       final PackageChooserDialog dialog = new PackageChooserDialog(ExecutionBundle.message("choose.package.dialog.title"), getProject());
676       dialog.show();
677       final PsiPackage aPackage = dialog.getSelectedPackage();
678       return aPackage != null ? aPackage.getQualifiedName() : null;
679     }
680   }
681
682   private class TestsChooserActionListener extends TestClassBrowser {
683     public TestsChooserActionListener(final Project project) {
684       super(project);
685     }
686
687     @Override
688     protected void onClassChoosen(PsiClass psiClass) {
689       final JTextField textField = myPatternTextField.getTextField();
690       final String text = textField.getText();
691       textField.setText(text + (text.length() > 0 ? "||" : "") + psiClass.getQualifiedName());
692     }
693
694     @Override
695     protected ClassFilter.ClassFilterWithScope getFilter() throws NoFilterException {
696       try {
697         return TestClassFilter.create(SourceScope.wholeProject(getProject()), null);
698       }
699       catch (JUnitUtil.NoJUnitException ignore) {
700         throw new NoFilterException(new MessagesEx.MessageInfo(getProject(),
701                                                                ignore.getMessage(),
702                                                                ExecutionBundle.message("cannot.browse.test.inheritors.dialog.title")));
703       }
704     }
705
706     @Override
707     public void actionPerformed(ActionEvent e) {
708       showDialog();
709     }
710   }
711
712   private class TestClassBrowser extends ClassBrowser {
713     public TestClassBrowser(final Project project) {
714       super(project, ExecutionBundle.message("choose.test.class.dialog.title"));
715     }
716
717     protected void onClassChoosen(final PsiClass psiClass) {
718       setPackage(JUnitUtil.getContainingPackage(psiClass));
719     }
720
721     protected PsiClass findClass(final String className) {
722       return getModuleSelector().findClass(className);
723     }
724
725     protected ClassFilter.ClassFilterWithScope getFilter() throws NoFilterException {
726       final ConfigurationModuleSelector moduleSelector = getModuleSelector();
727       final Module module = moduleSelector.getModule();
728       if (module == null) {
729         throw NoFilterException.moduleDoesntExist(moduleSelector);
730       }
731       final ClassFilter.ClassFilterWithScope classFilter;
732       try {
733         final JUnitConfiguration configurationCopy =
734           new JUnitConfiguration(ExecutionBundle.message("default.junit.configuration.name"), getProject(),
735                                  JUnitConfigurationType.getInstance().getConfigurationFactories()[0]);
736         applyEditorTo(configurationCopy);
737         classFilter = TestClassFilter
738           .create(SourceScope.modulesWithDependencies(configurationCopy.getModules()), configurationCopy.getConfigurationModule().getModule());
739       }
740       catch (JUnitUtil.NoJUnitException e) {
741         throw NoFilterException.noJUnitInModule(module);
742       }
743       return classFilter;
744     }
745   }
746
747   private class CategoryBrowser extends ClassBrowser {
748     public CategoryBrowser(Project project) {
749       super(project, "Category Interface");
750     }
751
752     protected PsiClass findClass(final String className) {
753       return myModuleSelector.findClass(className);
754     }
755
756     protected ClassFilter.ClassFilterWithScope getFilter() throws NoFilterException {
757       final Module module = myModuleSelector.getModule();
758       final GlobalSearchScope scope;
759       if (module == null) {
760         scope = GlobalSearchScope.allScope(myProject);
761       }
762       else {
763         scope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module);
764       }
765       return new ClassFilter.ClassFilterWithScope() {
766         public GlobalSearchScope getScope() {
767           return scope;
768         }
769
770         public boolean isAccepted(final PsiClass aClass) {
771           return true;
772         }
773       };
774     }
775
776     @Override
777     protected void onClassChoosen(PsiClass psiClass) {
778       ((LabeledComponent<EditorTextFieldWithBrowseButton>)getTestLocation(JUnitConfigurationModel.CATEGORY)).getComponent()
779         .setText(psiClass.getQualifiedName());
780     }
781   }
782 }