package jetbrains.mps.ide.modelchecker.platform.actions;
/*Generated by MPS */
import javax.swing.JPanel;
import com.intellij.openapi.project.Project;
import jetbrains.mps.ide.findusages.view.UsagesView;
import javax.swing.JButton;
import jetbrains.mps.ide.project.ProjectHelper;
import java.awt.BorderLayout;
import jetbrains.mps.ide.findusages.view.treeholder.treeview.ViewOptions;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.icons.AllIcons;
import org.jetbrains.annotations.NotNull;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.IdeActions;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import jetbrains.mps.baseLanguage.closures.runtime.Wrappers;
import java.util.List;
import jetbrains.mps.smodel.ModelAccessHelper;
import jetbrains.mps.util.Computable;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import com.intellij.openapi.ui.Messages;
import java.util.ArrayList;
import java.util.Set;
import org.jetbrains.mps.openapi.model.SNodeReference;
import jetbrains.mps.internal.collections.runtime.SetSequence;
import java.util.HashSet;
import org.jetbrains.mps.openapi.model.SModel;
import jetbrains.mps.ide.findusages.model.SearchResult;
import jetbrains.mps.internal.collections.runtime.ISelector;
import jetbrains.mps.internal.collections.runtime.IWhereFilter;
import org.jetbrains.mps.openapi.module.SModule;
import jetbrains.mps.ide.findusages.model.SearchQuery;
import jetbrains.mps.ide.findusages.model.holders.GenericHolder;
import java.util.Collection;
import org.jetbrains.mps.openapi.module.SModuleReference;
import jetbrains.mps.project.GlobalScope;
import jetbrains.mps.ide.findusages.view.FindUtils;
import jetbrains.mps.findUsages.CompositeFinder;
import jetbrains.mps.ide.findusages.model.holders.ModelsHolder;
import org.jetbrains.mps.openapi.model.SModelReference;
import jetbrains.mps.ide.findusages.model.IResultProvider;
import com.intellij.openapi.actionSystem.ActionPlaces;
import org.jetbrains.annotations.Nullable;
import jetbrains.mps.ide.findusages.model.SearchResults;
import jetbrains.mps.ide.findusages.view.treeholder.treeview.INodeRepresentator;
import jetbrains.mps.ide.findusages.view.treeholder.tree.TextOptions;
import jetbrains.mps.util.NameUtil;
import javax.swing.Icon;
import jetbrains.mps.ide.icons.IdeIcons;
import jetbrains.mps.ide.messages.Icons;
import jetbrains.mps.util.StringUtil;
import jetbrains.mps.ide.findusages.model.CategoryKind;
import java.util.Arrays;
import org.jdom.Element;
import jetbrains.mps.ide.findusages.CantSaveSomethingException;
import jetbrains.mps.ide.findusages.CantLoadSomethingException;
public class ModelCheckerViewer extends JPanel {
private final Project myIdeaProject;
private final jetbrains.mps.project.Project myProject;
private UsagesView myUsagesView;
private JButton myFixButton;
private UsagesView.RerunAction myCheckAction;
public ModelCheckerViewer(Project project) {
this(project, true);
}
public ModelCheckerViewer(Project project, boolean canFix) {
myIdeaProject = project;
myProject = ProjectHelper.toMPSProject(project);
setLayout(new BorderLayout());
ViewOptions viewOptions = new ViewOptions(true, false, false, false, false);
viewOptions.myCategories = new boolean[]{true, false};
myUsagesView = new UsagesView(project, viewOptions);
myCheckAction = new UsagesView.RerunAction(myUsagesView, "Check again");
myUsagesView.setActions(myCheckAction, new UsagesView.RebuildAction(myUsagesView), new AnAction("Close", "", AllIcons.Actions.Cancel) {
public void actionPerformed(@NotNull AnActionEvent p0) {
ModelCheckerViewer.this.close();
}
}, ActionManager.getInstance().getAction(IdeActions.ACTION_PIN_ACTIVE_TAB));
myUsagesView.setCustomNodeRepresentator(new ModelCheckerViewer.MyNodeRepresentator());
add(myUsagesView.getComponent(), BorderLayout.CENTER);
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
// XXX fix button might be an action along with others above (i.e. button in the left pane)
if (canFix) {
myFixButton = new JButton("Perform Quick Fixes");
myFixButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
performQuickFixes();
}
});
buttonPanel.add(myFixButton);
}
add(buttonPanel, BorderLayout.SOUTH);
}
protected void close() {
// no-op, override to react on view close action
}
public void performQuickFixes() {
// Ask if need to fix
// Perform quick fixes
final Wrappers._int fixedTotal = new Wrappers._int(0);
// Select all fixable issues
final List<ModelCheckerIssue> issuesToFix = new ModelAccessHelper(myProject.getModelAccess()).runReadAction(new Computable<List<ModelCheckerIssue>>() {
public List<ModelCheckerIssue> compute() {
return getIssuesToFix();
}
});
if (ListSequence.fromList(issuesToFix).isEmpty()) {
Messages.showInfoMessage("There are no quick fixes for current problems", "No Quick Fixes");
return;
}
int dialogAnswer = Messages.showYesNoDialog(myIdeaProject, "You are going to remove undeclared properties, children from nodes and resolve references. " + "You may not be able to undo it. Are you sure?", "Warning", null);
if (dialogAnswer != 0) {
return;
}
myProject.getModelAccess().executeCommandInEDT(new Runnable() {
public void run() {
while (true) {
int fixedBefore = fixedTotal.value;
for (ModelCheckerIssue issue : ListSequence.fromListWithValues(new ArrayList<ModelCheckerIssue>(), issuesToFix)) {
if (issue.fix()) {
fixedTotal.value++;
ListSequence.fromList(issuesToFix).removeElement(issue);
}
}
if (fixedBefore == fixedTotal.value) {
break;
}
}
}
});
// Perform recheck if needed
if (fixedTotal.value != 0) {
int dialogAnswer1 = Messages.showYesNoDialog(myIdeaProject, "Model checker fixed " + fixedTotal.value + " issues. Do you wish to recheck?", "Recheck", null);
if (dialogAnswer1 != 0) {
return;
}
doReCheck();
}
}
private List<ModelCheckerIssue> getIssuesToFix() {
final Set<SNodeReference> includedResultNodes = SetSequence.fromSetWithValues(new HashSet<SNodeReference>(), myUsagesView.getIncludedResultNodes());
final Set<SModel> includedResultModels = SetSequence.fromSetWithValues(new HashSet<SModel>(), myUsagesView.getIncludedModels());
return ListSequence.fromList(((List<SearchResult<ModelCheckerIssue>>) getSearchResults().getSearchResults())).select(new ISelector<SearchResult<ModelCheckerIssue>, ModelCheckerIssue>() {
public ModelCheckerIssue select(SearchResult<ModelCheckerIssue> sr) {
return sr.getObject();
}
}).where(new IWhereFilter<ModelCheckerIssue>() {
public boolean accept(ModelCheckerIssue sr) {
boolean isNodeIssueAndFixable = sr instanceof ModelCheckerIssue.NodeIssue && SetSequence.fromSet(includedResultNodes).contains(((ModelCheckerIssue.NodeIssue) sr).getNode().getReference()) && sr.isFixable();
boolean isModelIssueAndFixable = sr instanceof ModelCheckerIssue.ModelIssue && SetSequence.fromSet(includedResultModels).contains(((ModelCheckerIssue.ModelIssue) sr).getModel()) && sr.isFixable();
return isNodeIssueAndFixable || isModelIssueAndFixable;
}
}).toListSequence();
}
/*package*/ void checkModules(List<SModule> modules, String taskTargetTitle) {
SearchQuery query = new SearchQuery(new GenericHolder<Collection<SModuleReference>>(ListSequence.fromList(modules).select(new ISelector<SModule, SModuleReference>() {
public SModuleReference select(SModule it) {
return it.getModuleReference();
}
}).toListSequence()), GlobalScope.getInstance());
runCheck(FindUtils.makeProvider(new CompositeFinder(newModelChecker())), query, taskTargetTitle);
}
/*package*/ void checkModels(List<SModel> models, String taskTargetTitle) {
runCheck(FindUtils.makeProvider(newModelChecker()), new SearchQuery(new ModelsHolder(ListSequence.fromList(models).select(new ISelector<SModel, SModelReference>() {
public SModelReference select(SModel it) {
return it.getReference();
}
}).toListSequence()), GlobalScope.getInstance()), taskTargetTitle);
}
/*package*/ void runCheck(IResultProvider resultProvider, SearchQuery searchQuery, String taskTargetTitle) {
myCheckAction.setProgressText(String.format("Checking %s", taskTargetTitle));
myCheckAction.setRunOptions(resultProvider, searchQuery);
doReCheck();
}
private void doReCheck() {
myCheckAction.actionPerformed(AnActionEvent.createFromInputEvent(myCheckAction, null, ActionPlaces.UNKNOWN));
}
public void dispose() {
myUsagesView.dispose();
}
@Nullable
public SearchResults<ModelCheckerIssue> getSearchResults() {
return myUsagesView.getSearchResults();
}
public void setSearchResults(SearchResults<ModelCheckerIssue> issues) {
myUsagesView.setContents(issues);
}
private ModelCheckerIssueFinder newModelChecker() {
return new ModelCheckerIssueFinder(ModelCheckerSettings.getInstance().getSpecificCheckers(myProject));
}
public static class MyNodeRepresentator implements INodeRepresentator<ModelCheckerIssue> {
public MyNodeRepresentator() {
}
@Override
public String getResultsText(TextOptions options) {
int size = options.mySubresultsCount;
return "<strong>" + NameUtil.formatNumericalString(size, "issue") + " found</strong>";
}
@Override
public Icon getResultsIcon() {
return IdeIcons.CLOSED_FOLDER;
}
@Override
public String getCategoryText(TextOptions options, String category, boolean isResultsSection) {
String counter = "";
if (options.myCounters && isResultsSection) {
counter = " (" + NameUtil.formatNumericalString(options.mySubresultsCount, "issue") + ")";
}
return "<strong>" + category + counter + "</strong>";
}
@Override
public Icon getCategoryIcon(String category) {
if ((category != null && category.length() > 0)) {
if (category.startsWith(ModelChecker.SEVERITY_ERROR)) {
return Icons.ERROR_ICON;
} else if (category.startsWith(ModelChecker.SEVERITY_WARNING)) {
return Icons.WARNING_ICON;
} else if (category.startsWith(ModelChecker.SEVERITY_INFO)) {
return Icons.INFORMATION_ICON;
}
}
return IdeIcons.CLOSED_FOLDER;
}
@NotNull
@Override
public String getPresentation(ModelCheckerIssue issue) {
return StringUtil.escapeXml(issue.getMessage());
}
@Override
public List<CategoryKind> getCategoryKinds() {
return Arrays.asList(ModelCheckerIssue.CATEGORY_KIND_SEVERITY, ModelCheckerIssue.CATEGORY_KIND_ISSUE_TYPE);
}
@Override
public void write(Element element, jetbrains.mps.project.Project project) throws CantSaveSomethingException {
}
@Override
public void read(Element element, jetbrains.mps.project.Project project) throws CantLoadSomethingException {
}
}
}