fix "IDEA-221944 Deadlock on opening second project" and support preloading for proje...
[idea/community.git] / java / compiler / impl / src / com / intellij / compiler / options / ValidationConfigurable.java
1 // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package com.intellij.compiler.options;
3
4 import com.intellij.ide.util.ElementsChooser;
5 import com.intellij.openapi.compiler.Compiler;
6 import com.intellij.openapi.compiler.CompilerBundle;
7 import com.intellij.openapi.compiler.CompilerManager;
8 import com.intellij.openapi.compiler.Validator;
9 import com.intellij.openapi.compiler.options.ExcludedEntriesConfigurable;
10 import com.intellij.openapi.fileChooser.FileChooserDescriptor;
11 import com.intellij.openapi.module.Module;
12 import com.intellij.openapi.module.ModuleManager;
13 import com.intellij.openapi.options.Configurable;
14 import com.intellij.openapi.options.ConfigurationException;
15 import com.intellij.openapi.options.SearchableConfigurable;
16 import com.intellij.openapi.project.Project;
17 import com.intellij.openapi.roots.ModuleRootManager;
18 import com.intellij.openapi.roots.ProjectFileIndex;
19 import com.intellij.openapi.roots.ProjectRootManager;
20 import com.intellij.openapi.vfs.VirtualFile;
21 import com.intellij.ui.IdeBorderFactory;
22 import com.intellij.uiDesigner.core.GridConstraints;
23 import com.intellij.util.NullableFunction;
24 import com.intellij.util.SmartList;
25 import com.intellij.util.containers.ContainerUtil;
26 import com.intellij.util.ui.JBUI;
27 import gnu.trove.THashSet;
28 import gnu.trove.TObjectHashingStrategy;
29 import org.jetbrains.annotations.NotNull;
30
31 import javax.swing.*;
32 import java.util.*;
33
34 /**
35  * @author Dmitry Avdeev
36  */
37 public class ValidationConfigurable implements SearchableConfigurable, Configurable.NoScroll {
38
39   private JPanel myPanel;
40   private JCheckBox myValidateBox;
41   private ElementsChooser<Compiler> myValidators;
42   private JPanel myExcludedEntriesPanel;
43   private JPanel myValidatorsPanel;
44   private final Project myProject;
45   private final ValidationConfiguration myConfiguration;
46   private final ExcludedEntriesConfigurable myExcludedConfigurable;
47
48   public ValidationConfigurable(final Project project) {
49     myProject = project;
50     myConfiguration = ValidationConfiguration.getInstance(myProject);
51     myExcludedConfigurable = createExcludedConfigurable(project);
52
53     myValidatorsPanel.setBorder(IdeBorderFactory.createTitledBorder("Validators:", false, JBUI.insetsTop(8)).setShowLine(false));
54     myValidators.getEmptyText().setText(CompilerBundle.message("no.validators"));
55
56     myExcludedEntriesPanel.setBorder(IdeBorderFactory.createTitledBorder("Exclude from validation:", false, JBUI.insetsTop(8)).setShowLine(false));
57   }
58
59   private static ExcludedEntriesConfigurable createExcludedConfigurable(@NotNull Project project) {
60     ProjectFileIndex index = project.isDefault() ? null : ProjectRootManager.getInstance(project).getFileIndex();
61     final FileChooserDescriptor descriptor = new FileChooserDescriptor(true, true, false, false, false, true) {
62       @Override
63       public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) {
64         return super.isFileVisible(file, showHiddenFiles) && (index == null || !index.isExcluded(file));
65       }
66     };
67
68     List<VirtualFile> allContentRoots = new ArrayList<>();
69     for (final Module module: ModuleManager.getInstance(project).getModules()) {
70       final VirtualFile[] moduleContentRoots = ModuleRootManager.getInstance(module).getContentRoots();
71       Collections.addAll(allContentRoots, moduleContentRoots);
72     }
73     descriptor.setRoots(allContentRoots);
74     return new ExcludedEntriesConfigurable(project, descriptor, ValidationConfiguration.getExcludedEntriesConfiguration(project));
75   }
76
77   @Override
78   @NotNull
79   public String getId() {
80     return "project.validation";
81   }
82
83   @Override
84   public String getDisplayName() {
85     return CompilerBundle.message("validation.display.name");
86   }
87
88   @Override
89   public String getHelpTopic() {
90     return "reference.projectsettings.compiler.validation";
91   }
92
93   @Override
94   public JComponent createComponent() {
95     final GridConstraints constraints = new GridConstraints();
96     constraints.setFill(GridConstraints.FILL_BOTH);
97     myExcludedEntriesPanel.add(myExcludedConfigurable.createComponent(), constraints);
98     return myPanel;
99   }
100
101   @Override
102   public boolean isModified() {
103     List<Compiler> selectedElements = myValidators.getMarkedElements();
104     List<Compiler> markedValidators = getMarkedValidators();
105     if (markedValidators.size() != selectedElements.size()) {
106       return true;
107     }
108     Set<Compiler> set = new THashSet<>(selectedElements, new TObjectHashingStrategy<Compiler>() {
109       @Override
110       public int computeHashCode(Compiler object) {
111         return object.getDescription().hashCode();
112       }
113
114       @Override
115       public boolean equals(Compiler o1, Compiler o2) {
116         return o1.getDescription().equals(o2.getDescription());
117       }
118     });
119     return myConfiguration.isValidateOnBuild() != myValidateBox.isSelected() ||
120         set.retainAll(markedValidators) ||
121         myExcludedConfigurable.isModified();
122   }
123
124   @Override
125   public void apply() throws ConfigurationException {
126     myConfiguration.setValidateOnBuild(myValidateBox.isSelected());
127     for (int i = 0; i < myValidators.getElementCount(); i++) {
128       final Compiler validator = myValidators.getElementAt(i);
129       myConfiguration.setSelected(validator,  myValidators.isElementMarked(validator));
130     }
131     myExcludedConfigurable.apply();
132   }
133
134   @Override
135   public void reset() {
136     myValidateBox.setSelected(myConfiguration.isValidateOnBuild());
137     final List<Compiler> validators = getValidators();
138     Collections.sort(validators, Comparator.comparing(Compiler::getDescription));
139     myValidators.setElements(validators, false);
140     myValidators.markElements(getMarkedValidators());
141     myExcludedConfigurable.reset();
142   }
143
144   private List<Compiler> getMarkedValidators() {
145     final List<Compiler> validators = getValidators();
146     return ContainerUtil.mapNotNull(validators, (NullableFunction<Compiler, Compiler>)validator -> myConfiguration.isSelected(validator) ? validator : null);
147   }
148
149   private List<Compiler> getValidators() {
150     final CompilerManager compilerManager = CompilerManager.getInstance(myProject);
151     return new SmartList<>(compilerManager.getCompilers(Validator.class));
152   }
153
154   @Override
155   public void disposeUIResources() {
156     myExcludedConfigurable.disposeUIResources();
157   }
158
159   private void createUIComponents() {
160     myValidators = new ElementsChooser<Compiler>(true) {
161       @Override
162       protected String getItemText(@NotNull final Compiler validator) {
163         final String description = validator.getDescription();
164         return description.replace(" Validator", "").replace(" validator", "");
165       }
166     };
167   }
168 }