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 { } } }