class members refactoring refactoring
[fedora-idea.git] / source / com / intellij / testIntegration / createTest / CreateTestDialog.java
bloba57b05af264d1a179a36325ea40ee79b34286415
1 package com.intellij.testIntegration.createTest;
3 import com.intellij.CommonBundle;
4 import com.intellij.codeInsight.CodeInsightBundle;
5 import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix;
6 import com.intellij.ide.util.*;
7 import com.intellij.openapi.actionSystem.AnAction;
8 import com.intellij.openapi.actionSystem.AnActionEvent;
9 import com.intellij.openapi.actionSystem.CustomShortcutSet;
10 import com.intellij.openapi.application.ApplicationManager;
11 import com.intellij.openapi.application.ReadAction;
12 import com.intellij.openapi.application.Result;
13 import com.intellij.openapi.command.WriteCommandAction;
14 import com.intellij.openapi.extensions.Extensions;
15 import com.intellij.openapi.help.HelpManager;
16 import com.intellij.openapi.module.Module;
17 import com.intellij.openapi.project.Project;
18 import com.intellij.openapi.roots.ContentEntry;
19 import com.intellij.openapi.roots.ModuleRootManager;
20 import com.intellij.openapi.roots.SourceFolder;
21 import com.intellij.openapi.ui.DialogWrapper;
22 import com.intellij.openapi.ui.Messages;
23 import com.intellij.openapi.util.IconLoader;
24 import com.intellij.openapi.util.Pair;
25 import com.intellij.openapi.vfs.VirtualFile;
26 import com.intellij.psi.*;
27 import com.intellij.refactoring.PackageWrapper;
28 import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesUtil;
29 import com.intellij.refactoring.ui.MemberSelectionTable;
30 import com.intellij.refactoring.util.RefactoringMessageUtil;
31 import com.intellij.refactoring.util.RefactoringUtil;
32 import com.intellij.refactoring.util.classMembers.MemberInfo;
33 import com.intellij.testIntegration.TestFrameworkDescriptor;
34 import com.intellij.testIntegration.TestIntegrationUtils;
35 import com.intellij.ui.*;
36 import com.intellij.util.IncorrectOperationException;
37 import org.jetbrains.annotations.NotNull;
39 import javax.swing.*;
40 import javax.swing.event.DocumentEvent;
41 import java.awt.*;
42 import java.awt.event.ActionEvent;
43 import java.awt.event.ActionListener;
44 import java.awt.event.InputEvent;
45 import java.awt.event.KeyEvent;
46 import java.util.*;
47 import java.util.List;
49 public class CreateTestDialog extends DialogWrapper {
50 private static final String RECENTS_KEY = "CreateTestDialog.RecentsKey";
51 private static final String DEFAULT_LIBRARY_NAME_PROPERTY = CreateTestDialog.class.getName() + ".defaultLibrary";
52 private static final String SHOW_INHERITED_MEMBERS_PROPERTY = CreateTestDialog.class.getName() + ".includeInheritedMembers";
54 private final Project myProject;
55 private final PsiClass myTargetClass;
56 private final Module myTargetModule;
58 private PsiDirectory myTargetDirectory;
59 private TestFrameworkDescriptor mySelectedTestDescriptor;
61 private final List<JRadioButton> myLibraryButtons = new ArrayList<JRadioButton>();
62 private JTextField myTargetClassNameField;
63 private ReferenceEditorWithBrowseButton mySuperClassField;
64 private ReferenceEditorComboWithBrowseButton myTargetPackageField;
65 private JCheckBox myGenerateBeforeBox;
66 private JCheckBox myGenerateAfterBox;
67 private JCheckBox myShowInheritedMethodsBox;
68 private MemberSelectionTable myMethodsTable;
69 private JButton myFixLibraryButton;
70 private JPanel myFixLibraryPanel;
71 private JLabel myFixLibraryLabel;
73 private JRadioButton myDefaultLibraryButton;
75 public CreateTestDialog(@NotNull Project project,
76 @NotNull String title,
77 PsiClass targetClass,
78 PsiPackage targetPackage,
79 Module targetModule) {
80 super(project, true);
81 myProject = project;
83 myTargetClass = targetClass;
84 myTargetModule = targetModule;
86 initControls(targetClass, targetPackage);
87 setTitle(title);
88 init();
90 myDefaultLibraryButton.doClick();
93 private void initControls(PsiClass targetClass, PsiPackage targetPackage) {
94 ButtonGroup group = new ButtonGroup();
96 Map<String, JRadioButton> nameToButtonMap = new HashMap<String, JRadioButton>();
97 List<Pair<String, JRadioButton>> attachedLibraries = new ArrayList<Pair<String, JRadioButton>>();
99 for (final TestFrameworkDescriptor descriptor : Extensions.getExtensions(TestFrameworkDescriptor.EXTENSION_NAME)) {
100 final JRadioButton b = new JRadioButton(descriptor.getName());
101 myLibraryButtons.add(b);
102 group.add(b);
104 nameToButtonMap.put(descriptor.getName(), b);
105 if (descriptor.isLibraryAttached(myTargetModule)) {
106 attachedLibraries.add(Pair.create(descriptor.getName(), b));
109 b.addActionListener(new ActionListener() {
110 public void actionPerformed(ActionEvent e) {
111 if (b.isSelected()) onLibrarySelected(descriptor);
116 String defaultLibrary = getDefaultLibraryName();
117 if (attachedLibraries.isEmpty()) {
118 if (defaultLibrary != null) {
119 myDefaultLibraryButton = nameToButtonMap.get(defaultLibrary);
122 else {
123 if (defaultLibrary != null) {
124 for (Pair<String, JRadioButton> each : attachedLibraries) {
125 if (each.first.equals(defaultLibrary)) {
126 myDefaultLibraryButton = each.second;
130 myDefaultLibraryButton = attachedLibraries.get(0).second;
132 if (myDefaultLibraryButton == null) {
133 myDefaultLibraryButton = myLibraryButtons.get(0);
136 myFixLibraryButton = new JButton(CodeInsightBundle.message("intention.create.test.dialog.fix.library"));
137 myFixLibraryButton.addActionListener(new ActionListener() {
138 public void actionPerformed(ActionEvent e) {
139 ApplicationManager.getApplication().runWriteAction(new Runnable() {
140 public void run() {
141 OrderEntryFix.addJarToRoots(mySelectedTestDescriptor.getLibraryPath(), myTargetModule);
144 myFixLibraryPanel.setVisible(false);
148 myTargetClassNameField = new JTextField(targetClass.getName() + "Test");
149 setPreferredSize(myTargetClassNameField);
150 myTargetClassNameField.getDocument().addDocumentListener(new DocumentAdapter() {
151 protected void textChanged(DocumentEvent e) {
152 getOKAction().setEnabled(JavaPsiFacade.getInstance(myProject).getNameHelper().isIdentifier(getClassName()));
156 mySuperClassField = JavaReferenceEditorUtil
157 .createReferenceEditorWithBrowseButton(new MyChooseSuperClassAction(), "", PsiManager.getInstance(myProject), true);
158 mySuperClassField.setMinimumSize(mySuperClassField.getPreferredSize());
160 String targetPackageName = targetPackage != null ? targetPackage.getQualifiedName() : "";
161 myTargetPackageField = new ReferenceEditorComboWithBrowseButton(new ActionListener() {
162 public void actionPerformed(final ActionEvent e) {
163 doSelectPackage();
165 }, targetPackageName, PsiManager.getInstance(myProject), false, RECENTS_KEY);
167 new AnAction() {
168 public void actionPerformed(AnActionEvent e) {
169 myTargetPackageField.getButton().doClick();
171 }.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.SHIFT_DOWN_MASK)),
172 myTargetPackageField.getChildComponent());
174 myGenerateBeforeBox = new JCheckBox("setUp/@Before");
175 myGenerateAfterBox = new JCheckBox("tearDown/@After");
177 myShowInheritedMethodsBox = new JCheckBox(CodeInsightBundle.message("intention.create.test.dialog.show.inherited"));
178 myShowInheritedMethodsBox.addActionListener(new ActionListener() {
179 public void actionPerformed(ActionEvent e) {
180 updateMethodsTable();
183 restoreShowInheritedMembersStatus();
184 myMethodsTable = new MemberSelectionTable(Collections.<MemberInfo>emptyList(), null);
185 updateMethodsTable();
188 private void onLibrarySelected(TestFrameworkDescriptor descriptor) {
189 String text = CodeInsightBundle.message("intention.create.test.dialog.library.not.found", descriptor.getName());
190 myFixLibraryLabel.setText(text);
191 myFixLibraryPanel.setVisible(!descriptor.isLibraryAttached(myTargetModule));
193 String superClass = descriptor.getDefaultSuperClass();
194 mySuperClassField.setText(superClass == null ? "" : superClass);
195 mySelectedTestDescriptor = descriptor;
198 private void setPreferredSize(JTextField field) {
199 Dimension size = field.getPreferredSize();
200 FontMetrics fontMetrics = field.getFontMetrics(field.getFont());
201 size.width = fontMetrics.charWidth('a') * 40;
202 field.setPreferredSize(size);
205 private void updateMethodsTable() {
206 List<MemberInfo> methods = TestIntegrationUtils.extractClassMethods(
207 myTargetClass, myShowInheritedMethodsBox.isSelected());
209 Set<PsiMember> selectedMethods = new HashSet<PsiMember>();
210 for (MemberInfo each : myMethodsTable.getSelectedMemberInfos()) {
211 selectedMethods.add(each.getMember());
213 for (MemberInfo each : methods) {
214 each.setChecked(selectedMethods.contains(each.getMember()));
217 myMethodsTable.setMemberInfos(methods);
220 private void doSelectPackage() {
221 PackageChooserDialog d = new PackageChooserDialog(CodeInsightBundle.message("dialog.create.class.package.chooser.title"), myProject);
222 d.selectPackage(myTargetPackageField.getText());
223 d.show();
224 PsiPackage p = d.getSelectedPackage();
225 if (p != null) myTargetPackageField.setText(p.getQualifiedName());
228 private String getDefaultLibraryName() {
229 return getProperties().getValue(DEFAULT_LIBRARY_NAME_PROPERTY);
232 private void saveDefaultLibraryName() {
233 getProperties().setValue(DEFAULT_LIBRARY_NAME_PROPERTY, mySelectedTestDescriptor.getName());
236 private void restoreShowInheritedMembersStatus() {
237 String v = getProperties().getValue(SHOW_INHERITED_MEMBERS_PROPERTY);
238 myShowInheritedMethodsBox.setSelected(v != null && v.equals("true"));
241 private void saveShowInheritedMembersStatus() {
242 boolean v = myShowInheritedMethodsBox.isSelected();
243 getProperties().setValue(SHOW_INHERITED_MEMBERS_PROPERTY, Boolean.toString(v));
246 private PropertiesComponent getProperties() {
247 return PropertiesComponent.getInstance(myProject);
250 @Override
251 protected String getDimensionServiceKey() {
252 return getClass().getName();
255 protected Action[] createActions() {
256 return new Action[]{getOKAction(), getCancelAction(), getHelpAction()};
259 public JComponent getPreferredFocusedComponent() {
260 return myTargetClassNameField;
263 protected JComponent createCenterPanel() {
264 JPanel panel = new JPanel(new GridBagLayout());
265 panel.setBorder(IdeBorderFactory.createBorder());
267 GridBagConstraints constr = new GridBagConstraints();
269 constr.fill = GridBagConstraints.HORIZONTAL;
270 constr.anchor = GridBagConstraints.WEST;
272 JPanel librariesPanel = new JPanel();
273 BoxLayout l = new BoxLayout(librariesPanel, BoxLayout.X_AXIS);
274 librariesPanel.setLayout(l);
276 for (JRadioButton b : myLibraryButtons) {
277 librariesPanel.add(b);
280 constr.insets = insets(4);
281 constr.gridy = 1;
282 constr.gridx = 0;
283 constr.weightx = 0;
284 panel.add(new JLabel(CodeInsightBundle.message("intention.create.test.dialog.testing.library")), constr);
286 constr.gridx = 1;
287 constr.weightx = 1;
288 constr.gridwidth = GridBagConstraints.REMAINDER;
289 panel.add(librariesPanel, constr);
291 myFixLibraryPanel = new JPanel(new BorderLayout());
292 myFixLibraryLabel = new JLabel();
293 myFixLibraryLabel.setIcon(IconLoader.getIcon("/actions/intentionBulb.png"));
294 myFixLibraryPanel.add(myFixLibraryLabel, BorderLayout.CENTER);
295 myFixLibraryPanel.add(myFixLibraryButton, BorderLayout.EAST);
297 constr.insets = insets(1);
298 constr.gridy = 2;
299 constr.gridx = 0;
300 panel.add(myFixLibraryPanel, constr);
302 constr.gridheight = 1;
304 constr.insets = insets(6);
305 constr.gridy = 3;
306 constr.gridx = 0;
307 constr.weightx = 0;
308 constr.gridwidth = 1;
309 panel.add(new JLabel(CodeInsightBundle.message("intention.create.test.dialog.class.name")), constr);
311 constr.gridx = 1;
312 constr.weightx = 1;
313 panel.add(myTargetClassNameField, constr);
315 constr.insets = insets(1);
316 constr.gridy = 4;
317 constr.gridx = 0;
318 constr.weightx = 0;
319 panel.add(new JLabel(CodeInsightBundle.message("intention.create.test.dialog.super.class")), constr);
321 constr.gridx = 1;
322 constr.weightx = 1;
323 panel.add(mySuperClassField, constr);
325 constr.insets = insets(1);
326 constr.gridy = 5;
327 constr.gridx = 0;
328 constr.weightx = 0;
329 panel.add(new JLabel(CodeInsightBundle.message("dialog.create.class.destination.package.label")), constr);
331 constr.gridx = 1;
332 constr.weightx = 1;
334 JPanel targetPackagePanel = new JPanel(new BorderLayout());
335 targetPackagePanel.add(myTargetPackageField, BorderLayout.CENTER);
336 panel.add(targetPackagePanel, constr);
338 constr.insets = insets(6);
339 constr.gridy = 6;
340 constr.gridx = 0;
341 constr.weightx = 0;
342 panel.add(new JLabel(CodeInsightBundle.message("intention.create.test.dialog.generate")), constr);
344 constr.gridx = 1;
345 constr.weightx = 1;
346 panel.add(myGenerateBeforeBox, constr);
348 constr.insets = insets(1);
349 constr.gridy = 7;
350 panel.add(myGenerateAfterBox, constr);
352 constr.insets = insets(6);
353 constr.gridy = 8;
354 constr.gridx = 0;
355 constr.weightx = 0;
356 panel.add(new JLabel(CodeInsightBundle.message("intention.create.test.dialog.select.methods")), constr);
358 constr.gridx = 1;
359 constr.weightx = 1;
360 panel.add(myShowInheritedMethodsBox, constr);
362 constr.insets = insets(1, 8);
363 constr.gridy = 9;
364 constr.gridx = 0;
365 constr.gridwidth = GridBagConstraints.REMAINDER;
366 constr.fill = GridBagConstraints.BOTH;
367 constr.weighty = 1;
368 panel.add(new JScrollPane(myMethodsTable), constr);
370 return panel;
373 private static Insets insets(int top) {
374 return insets(top, 0);
377 private static Insets insets(int top, int bottom) {
378 return new Insets(top, 8, bottom, 8);
381 public String getClassName() {
382 return myTargetClassNameField.getText();
385 public String getSuperClassName() {
386 String result = mySuperClassField.getText().trim();
387 if (result.length() == 0) return null;
388 return result;
391 public PsiDirectory getTargetDirectory() {
392 return myTargetDirectory;
395 public Collection<MemberInfo> getSelectedMethods() {
396 return myMethodsTable.getSelectedMemberInfos();
399 public boolean shouldGeneratedAfter() {
400 return myGenerateAfterBox.isSelected();
403 public boolean shouldGeneratedBefore() {
404 return myGenerateBeforeBox.isSelected();
407 public TestFrameworkDescriptor getSelectedTestFrameworkDescriptor() {
408 return mySelectedTestDescriptor;
411 protected void doOKAction() {
412 RecentsManager.getInstance(myProject).registerRecentEntry(RECENTS_KEY, myTargetPackageField.getText());
414 String errorMessage = null;
415 try {
416 myTargetDirectory = selectTargetDirectory();
417 if (myTargetDirectory == null) return;
418 errorMessage = RefactoringMessageUtil.checkCanCreateClass(myTargetDirectory, getClassName());
420 catch (IncorrectOperationException e) {
421 errorMessage = e.getMessage();
424 if (errorMessage != null) {
425 Messages.showMessageDialog(myProject, errorMessage, CommonBundle.getErrorTitle(), Messages.getErrorIcon());
428 saveDefaultLibraryName();
429 saveShowInheritedMembersStatus();
430 super.doOKAction();
433 private PsiDirectory selectTargetDirectory() throws IncorrectOperationException {
434 final String packageName = getPackageName();
435 final PackageWrapper targetPackage = new PackageWrapper(PsiManager.getInstance(myProject), packageName);
437 final VirtualFile selectedRoot = new ReadAction<VirtualFile>() {
438 protected void run(Result<VirtualFile> result) throws Throwable {
439 VirtualFile[] roots = ModuleRootManager.getInstance(myTargetModule).getSourceRoots();
440 if (roots.length == 0) return;
442 if (roots.length == 1) {
443 result.setResult(roots[0]);
445 else {
446 PsiDirectory defaultDir = chooseDefaultDirectory(packageName);
447 result.setResult(MoveClassesOrPackagesUtil.chooseSourceRoot(targetPackage, roots, defaultDir));
450 }.execute().getResultObject();
452 if (selectedRoot == null) return null;
454 return new WriteCommandAction<PsiDirectory>(myProject, CodeInsightBundle.message("create.directory.command")) {
455 protected void run(Result<PsiDirectory> result) throws Throwable {
456 result.setResult(RefactoringUtil.createPackageDirectoryInSourceRoot(targetPackage, selectedRoot));
458 }.execute().getResultObject();
461 private PsiDirectory chooseDefaultDirectory(String packageName) {
462 for (ContentEntry e : ModuleRootManager.getInstance(myTargetModule).getContentEntries()) {
463 for (SourceFolder f : e.getSourceFolders()) {
464 if (f.getFile() != null && f.isTestSource()) {
465 return PsiManager.getInstance(myProject).findDirectory(f.getFile());
469 return PackageUtil.findPossiblePackageDirectoryInModule(myTargetModule, packageName);
472 private String getPackageName() {
473 String name = myTargetPackageField.getText();
474 return name != null ? name.trim() : "";
477 @Override
478 protected void doHelpAction() {
479 HelpManager.getInstance().invokeHelp("reference.dialogs.createTest");
482 private class MyChooseSuperClassAction implements ActionListener {
483 public void actionPerformed(ActionEvent e) {
484 TreeClassChooserFactory f = TreeClassChooserFactory.getInstance(myProject);
485 TreeClassChooser dialog =
486 f.createAllProjectScopeChooser(CodeInsightBundle.message("intention.create.test.dialog.choose.super.class"));
487 dialog.showDialog();
488 PsiClass aClass = dialog.getSelectedClass();
489 if (aClass != null) {
490 mySuperClassField.setText(aClass.getQualifiedName());