From c9110059531f211b1993310c0c363bbe7cd9c433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vojt=C4=9Bch=20Kr=C3=A1sa?= Date: Thu, 6 Jun 2019 18:52:12 +0200 Subject: [PATCH] #40 conflict false negative --- META-INF/plugin.xml | 6 +- src/krasa/mavenhelper/analyzer/GuiForm.form | 26 +++++- src/krasa/mavenhelper/analyzer/GuiForm.java | 61 +++++++++++-- .../mavenhelper/analyzer/MyListNode.java | 17 +--- .../analyzer/MyTreeUserObject.java | 56 ++++-------- .../mavenhelper/analyzer/TreeRenderer.java | 87 +++++++++++++++---- src/krasa/mavenhelper/analyzer/Utils.java | 26 ++++++ 7 files changed, 201 insertions(+), 78 deletions(-) create mode 100644 src/krasa/mavenhelper/analyzer/Utils.java diff --git a/META-INF/plugin.xml b/META-INF/plugin.xml index 90b6532..fae50f8 100644 --- a/META-INF/plugin.xml +++ b/META-INF/plugin.xml @@ -2,7 +2,7 @@ MavenRunHelper Maven Helper - 4.4.183.4139.0 + 4.5.183.4139.0 Vojtech Krasa @@ -38,6 +38,8 @@ ]]> 4.5 +
- Fixed conflict false negative due to a bugged dependency resolution by IntelliJ
4.4
- Goals rearranging fixed
4.3 @@ -135,7 +137,7 @@ description="Run New Maven Goal..." icon="/krasa/mavenhelper/icons/runMaven.png"> - + diff --git a/src/krasa/mavenhelper/analyzer/GuiForm.form b/src/krasa/mavenhelper/analyzer/GuiForm.form index 2bef775..d2cd907 100644 --- a/src/krasa/mavenhelper/analyzer/GuiForm.form +++ b/src/krasa/mavenhelper/analyzer/GuiForm.form @@ -15,7 +15,7 @@ - + @@ -42,7 +42,7 @@ - + @@ -224,6 +224,28 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/krasa/mavenhelper/analyzer/GuiForm.java b/src/krasa/mavenhelper/analyzer/GuiForm.java index f7636ec..2fe31da 100644 --- a/src/krasa/mavenhelper/analyzer/GuiForm.java +++ b/src/krasa/mavenhelper/analyzer/GuiForm.java @@ -1,6 +1,7 @@ package krasa.mavenhelper.analyzer; import com.intellij.icons.AllIcons; +import com.intellij.ide.BrowserUtil; import com.intellij.ide.CommonActionsManager; import com.intellij.ide.DefaultTreeExpander; import com.intellij.ide.util.PropertiesComponent; @@ -97,6 +98,8 @@ public int compare(MavenArtifactNode o1, MavenArtifactNode o2) { private JPanel buttonsPanel; private JButton donate; private JButton reimport; + protected JEditorPane intellijBugLabel; + protected JEditorPane falsePositive; protected DefaultListModel listDataModel; protected Map> allArtifactsMap; protected final DefaultTreeModel rightTreeModel; @@ -125,6 +128,42 @@ public GuiForm(final Project project, VirtualFile file, final MavenProject maven mavenProjectsManager = MavenProjectsManager.getInstance(project); myProjectService = MyProjectService.getInstance(project); this.mavenProject = mavenProject; + + intellijBugLabel.setText("\n" + + " \n" + + "\n" + + " \n" + + " \n" + + " 1) An artifact is in conflict, its version is probably wrongly resolved due to a bug in IntelliJ." + + " \n" + + "\n"); + intellijBugLabel.setBackground(rootPanel.getBackground()); + intellijBugLabel.setForeground(SimpleTextAttributes.ERROR_ATTRIBUTES.getFgColor()); + intellijBugLabel.setVisible(false); + intellijBugLabel.addHyperlinkListener(e -> { + if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + BrowserUtil.browse(e.getURL()); + } + }); + + + falsePositive.setText("\n" + + " \n" + + "\n" + + " \n" + + " \n" + + " 2) Probably a false positive, this should not happen, please report it at GitHub." + + " \n" + + "\n"); + falsePositive.setBackground(rootPanel.getBackground()); + falsePositive.setForeground(SimpleTextAttributes.ERROR_ATTRIBUTES.getFgColor()); + falsePositive.setVisible(false); + falsePositive.addHyperlinkListener(e -> { + if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + BrowserUtil.browse(e.getURL()); + } + }); + final ActionListener radioButtonListener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -193,6 +232,8 @@ public void actionPerformed(ActionEvent e) { } }); noConflictsWarningLabel.setText(WARNING); + noConflictsWarningLabel.setForeground(SimpleTextAttributes.ERROR_ATTRIBUTES.getFgColor()); + leftPanelLayout = (CardLayout) leftPanelWrapper.getLayout(); rightTreeRoot = new DefaultMutableTreeNode(); @@ -201,7 +242,7 @@ public void actionPerformed(ActionEvent e) { rightTree.setRootVisible(false); rightTree.setShowsRootHandles(true); rightTree.expandPath(new TreePath(rightTreeRoot.getPath())); - rightTree.setCellRenderer(new TreeRenderer(showGroupId)); + rightTree.setCellRenderer(new TreeRenderer(showGroupId, this)); rightTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); rightTreePopupHandler = new RightTreePopupHandler(project, mavenProject, rightTree); rightTree.addMouseListener(rightTreePopupHandler); @@ -214,7 +255,7 @@ public void actionPerformed(ActionEvent e) { leftTree.setRootVisible(false); leftTree.setShowsRootHandles(true); leftTree.expandPath(new TreePath(leftTreeRoot.getPath())); - leftTree.setCellRenderer(new TreeRenderer(showGroupId)); + leftTree.setCellRenderer(new TreeRenderer(showGroupId, this)); leftTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); leftTreePopupHandler = new LeftTreePopupHandler(project, mavenProject, leftTree); leftTree.addMouseListener(leftTreePopupHandler); @@ -335,7 +376,7 @@ public void valueChanged(TreeSelectionEvent e) { final String key = getArtifactKey(userObject.getArtifact()); List mavenArtifactNodes = allArtifactsMap.get(key); if (mavenArtifactNodes != null) {// can be null while refreshing - fillRightTree(mavenArtifactNodes, sortByVersion(mavenArtifactNodes)); + fillRightTree(mavenArtifactNodes); } } } @@ -350,14 +391,14 @@ public void valueChanged(ListSelectionEvent e) { final MyListNode myListNode = (MyListNode) leftPanelList.getSelectedValue(); List artifacts = myListNode.value; - fillRightTree(artifacts, myListNode.getRightVersion()); + fillRightTree(artifacts); } } - private void fillRightTree(List mavenArtifactNodes, String rightVersion) { + private void fillRightTree(List mavenArtifactNodes) { rightTreeRoot.removeAllChildren(); for (MavenArtifactNode mavenArtifactNode : mavenArtifactNodes) { - MyTreeUserObject userObject = MyTreeUserObject.create(mavenArtifactNode, rightVersion); + MyTreeUserObject userObject = new MyTreeUserObject(mavenArtifactNode); userObject.showOnlyVersion = true; final DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(userObject); fillRightTree(mavenArtifactNode, newNode); @@ -379,6 +420,8 @@ private void fillRightTree(MavenArtifactNode mavenArtifactNode, DefaultMutableTr } private void initializeModel() { + intellijBugLabel.setVisible(false); + falsePositive.setVisible(false); rightTreePopupHandler.hidePopup(); leftTreePopupHandler.hidePopup(); @@ -398,6 +441,8 @@ private void initializeModel() { } private void updateLeftPanel() { + intellijBugLabel.setVisible(false); + falsePositive.setVisible(false); listDataModel.clear(); leftTreeRoot.removeAllChildren(); @@ -458,7 +503,7 @@ public void run() { } leftPanelLayout.show(leftPanelWrapper, "list"); - } else if (allDependenciesAsListRadioButton.isSelected()) { + } else if (allDependenciesAsListRadioButton.isSelected()) { //list for (Map.Entry> s : allArtifactsMap.entrySet()) { if (contains(searchFieldText, s.getKey())) { listDataModel.addElement(new MyListNode(s)); @@ -496,7 +541,7 @@ private boolean fillLeftTree(DefaultMutableTreeNode parent, List value; - protected String maxVersion; protected String rightVersion; protected boolean conflict; public MyListNode(Map.Entry> s) { key = s.getKey(); value = s.getValue(); - maxVersion = GuiForm.sortByVersion(value); initRightVersion(); initConflict(); } @@ -37,16 +35,11 @@ private void initRightVersion() { } private void initConflict() { - String lastVersion = null; if (value != null && !value.isEmpty()) { for (MavenArtifactNode mavenArtifactNode : value) { - if (mavenArtifactNode.getState() != MavenArtifactState.EXCLUDED) { - String version = mavenArtifactNode.getArtifact().getVersion(); - if (lastVersion != null && !lastVersion.equals(version)) { - conflict = true; - break; - } - lastVersion = version; + if (Utils.isOmitted(mavenArtifactNode) || Utils.isConflictAlternativeMethod(mavenArtifactNode)) { + conflict = true; + break; } } } @@ -56,10 +49,6 @@ public boolean isConflict() { return conflict; } - public String getMaxVersion() { - return maxVersion; - } - public String getRightVersion() { return rightVersion; } diff --git a/src/krasa/mavenhelper/analyzer/MyTreeUserObject.java b/src/krasa/mavenhelper/analyzer/MyTreeUserObject.java index a20b28d..5475b78 100644 --- a/src/krasa/mavenhelper/analyzer/MyTreeUserObject.java +++ b/src/krasa/mavenhelper/analyzer/MyTreeUserObject.java @@ -1,56 +1,38 @@ package krasa.mavenhelper.analyzer; -import com.intellij.ui.SimpleTextAttributes; -import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.maven.model.MavenArtifact; import org.jetbrains.idea.maven.model.MavenArtifactNode; -import org.jetbrains.idea.maven.model.MavenArtifactState; /** * @author Vojtech Krasa */ public class MyTreeUserObject { - private MavenArtifactNode mavenArtifactNode; - protected SimpleTextAttributes attributes; + private MavenArtifactNode mavenArtifactNode; - boolean showOnlyVersion = false; - boolean highlight; + boolean showOnlyVersion = false; + boolean highlight; - public MyTreeUserObject(MavenArtifactNode mavenArtifactNode) { - this.mavenArtifactNode = mavenArtifactNode; - this.attributes = SimpleTextAttributes.REGULAR_ATTRIBUTES; - } + public MyTreeUserObject(MavenArtifactNode mavenArtifactNode) { + this.mavenArtifactNode = mavenArtifactNode; + } - public MyTreeUserObject(MavenArtifactNode mavenArtifactNode, final SimpleTextAttributes regularAttributes) { - this.mavenArtifactNode = mavenArtifactNode; - this.attributes = regularAttributes; - } - - static MyTreeUserObject create(MavenArtifactNode mavenArtifactNode, @NotNull String rightVersion) { - SimpleTextAttributes attributes = SimpleTextAttributes.ERROR_ATTRIBUTES; - if (mavenArtifactNode.getState() == MavenArtifactState.ADDED - || (mavenArtifactNode.getRelatedArtifact() != null - && mavenArtifactNode.getRelatedArtifact().getVersion().equals(mavenArtifactNode.getArtifact().getVersion()))) { - attributes = SimpleTextAttributes.REGULAR_ATTRIBUTES; - } - return new MyTreeUserObject(mavenArtifactNode, attributes); - } public MavenArtifact getArtifact() { - return mavenArtifactNode.getArtifact(); - } + return mavenArtifactNode.getArtifact(); + } + + public MavenArtifactNode getMavenArtifactNode() { + return mavenArtifactNode; + } - public MavenArtifactNode getMavenArtifactNode() { - return mavenArtifactNode; - } + public boolean isHighlight() { + return highlight; + } - public boolean isHighlight() { - return highlight; - } + @Override + public String toString() { + return mavenArtifactNode.getArtifact().getArtifactId(); + } - @Override - public String toString() { - return mavenArtifactNode.getArtifact().getArtifactId(); - } } diff --git a/src/krasa/mavenhelper/analyzer/TreeRenderer.java b/src/krasa/mavenhelper/analyzer/TreeRenderer.java index 0579f15..d6b0ea2 100644 --- a/src/krasa/mavenhelper/analyzer/TreeRenderer.java +++ b/src/krasa/mavenhelper/analyzer/TreeRenderer.java @@ -3,6 +3,7 @@ import com.intellij.ui.ColoredTreeCellRenderer; import com.intellij.ui.JBColor; import com.intellij.ui.SimpleTextAttributes; +import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.model.MavenArtifact; import org.jetbrains.idea.maven.model.MavenArtifactNode; import org.jetbrains.idea.maven.model.MavenArtifactState; @@ -17,6 +18,7 @@ public class TreeRenderer extends ColoredTreeCellRenderer { private final JCheckBox showGroupId; + private final GuiForm guiForm; private final SimpleTextAttributes errorBoldAttributes; private final SimpleTextAttributes testAttributes; @@ -27,9 +29,11 @@ public class TreeRenderer extends ColoredTreeCellRenderer { private final SimpleTextAttributes runtimeAttributes; private final SimpleTextAttributes runtimeBoldAttributes; + public static final SimpleTextAttributes ITALIC_ERROR = SimpleTextAttributes.ERROR_ATTRIBUTES.derive(SimpleTextAttributes.STYLE_ITALIC, null, null, null); - public TreeRenderer(JCheckBox showGroupId) { + public TreeRenderer(JCheckBox showGroupId, GuiForm guiForm) { this.showGroupId = showGroupId; + this.guiForm = guiForm; errorBoldAttributes = new SimpleTextAttributes(SimpleTextAttributes.STYLE_BOLD, SimpleTextAttributes.ERROR_ATTRIBUTES.getFgColor()); testAttributes = new SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, new JBColor(new Color(4, 111, 0), new Color(0x69AF80))); @@ -57,18 +61,29 @@ public void customizeCellRenderer(JTree tree, Object value, boolean selected, bo } else { classifier = ""; } - + MavenArtifactNode mavenArtifactNode = myTreeUserObject.getMavenArtifactNode(); + boolean omitted = Utils.isOmitted(mavenArtifactNode); + boolean conflict_AlternativeMethod = Utils.isConflictAlternativeMethod(mavenArtifactNode); + boolean error = omitted || conflict_AlternativeMethod; String currentVersion = artifact.getVersion(); + + if (myTreeUserObject.showOnlyVersion) { - append(currentVersion + " [" + classifier + artifact.getScope() + "]", myTreeUserObject.attributes); - } else { - MavenArtifactNode mavenArtifactNode = myTreeUserObject.getMavenArtifactNode(); - boolean omitted = mavenArtifactNode.getState() == MavenArtifactState.CONFLICT - && (mavenArtifactNode.getRelatedArtifact() == null || !currentVersion.equals(mavenArtifactNode.getRelatedArtifact().getVersion())); + SimpleTextAttributes attributes = SimpleTextAttributes.REGULAR_ATTRIBUTES; + if (error) { + attributes = SimpleTextAttributes.ERROR_ATTRIBUTES; + } + append(currentVersion + " [" + classifier + artifact.getScope() + "]", attributes); + + checkForBug(myTreeUserObject); + if (!omitted && conflict_AlternativeMethod) { + conflict_AlternativeMethod(mavenArtifactNode, attributes, getConflictWinner(mavenArtifactNode)); + } + } else { SimpleTextAttributes attributes; SimpleTextAttributes boldAttributes; - if (omitted) { + if (error) { attributes = SimpleTextAttributes.ERROR_ATTRIBUTES; boldAttributes = errorBoldAttributes; } else if ("test".equals(myTreeUserObject.getArtifact().getScope())) { @@ -92,19 +107,61 @@ public void customizeCellRenderer(JTree tree, Object value, boolean selected, bo append(artifact.getGroupId() + " : ", attributes); } append(artifact.getArtifactId(), boldAttributes); + append(" : " + currentVersion, attributes); + append(" [" + classifier + artifact.getScope() + "]", attributes); - if (omitted) { - MavenArtifact relatedArtifact = mavenArtifactNode.getRelatedArtifact(); - String realVersion = null; - if (relatedArtifact != null) { - realVersion = relatedArtifact.getVersion(); + if (error) { + String winner = getConflictWinner(mavenArtifactNode); + + if (omitted) { + append(" (omitted for conflict with: " + winner + ")", attributes); + checkForBug(myTreeUserObject); + } else {//conflict_AlternativeMethod + conflict_AlternativeMethod(mavenArtifactNode, attributes, winner); } - append(" : " + currentVersion + " (omitted for conflict with " + realVersion + ")" + " [" + classifier + artifact.getScope() + "]", attributes); + } + + } + + } + + private void conflict_AlternativeMethod(MavenArtifactNode mavenArtifactNode, SimpleTextAttributes attributes, String realArtifact) { + append(" (artifact state: " + mavenArtifactNode.getState() + ", conflict with: " + realArtifact, attributes); + append(")", attributes); + append(" - 2)", ITALIC_ERROR); + guiForm.falsePositive.setVisible(true); + } + + @Nullable + private String getConflictWinner(MavenArtifactNode mavenArtifactNode) { + String realArtifact = "null"; + MavenArtifact conflictWinner = mavenArtifactNode.getRelatedArtifact(); + + if (conflictWinner != null) { + String realVersion; + String realClassifier; + realVersion = conflictWinner.getVersion(); + realClassifier = conflictWinner.getClassifier(); + String scope = conflictWinner.getScope(); + if (realClassifier != null) { + realClassifier = realClassifier + " - "; } else { - append(" : " + currentVersion + " [" + classifier + artifact.getScope() + "]", attributes); + realClassifier = ""; } + realArtifact = realVersion; +// realArtifact = realVersion + " [" + realClassifier + scope + "]"; } + return realArtifact; + } + private void checkForBug(MyTreeUserObject myTreeUserObject) { + MavenArtifactNode mavenArtifactNode = myTreeUserObject.getMavenArtifactNode(); + if (mavenArtifactNode.getState() == MavenArtifactState.CONFLICT && !Utils.isVersionMismatch(myTreeUserObject.getMavenArtifactNode())) { + append(" - 1)", ITALIC_ERROR); + guiForm.intellijBugLabel.setVisible(true); + } } + + } diff --git a/src/krasa/mavenhelper/analyzer/Utils.java b/src/krasa/mavenhelper/analyzer/Utils.java new file mode 100644 index 0000000..45eb459 --- /dev/null +++ b/src/krasa/mavenhelper/analyzer/Utils.java @@ -0,0 +1,26 @@ +package krasa.mavenhelper.analyzer; + +import com.intellij.openapi.diagnostic.Logger; +import org.jetbrains.idea.maven.model.MavenArtifactNode; +import org.jetbrains.idea.maven.model.MavenArtifactState; + +public class Utils { + private static final Logger LOG = com.intellij.openapi.diagnostic.Logger.getInstance(Utils.class); + + // myRelatedArtifact is a conflict winner, null means there was no conflict (probably) + public static boolean isVersionMatch(MavenArtifactNode mavenArtifactNode) { + return mavenArtifactNode.getRelatedArtifact() != null && mavenArtifactNode.getRelatedArtifact().getVersion().equals(mavenArtifactNode.getArtifact().getVersion()); + } + + public static boolean isVersionMismatch(MavenArtifactNode mavenArtifactNode) { + return mavenArtifactNode.getRelatedArtifact() != null && !mavenArtifactNode.getRelatedArtifact().getVersion().equals(mavenArtifactNode.getArtifact().getVersion()); + } + + static boolean isOmitted(MavenArtifactNode mavenArtifactNode) { + return mavenArtifactNode.getState() == MavenArtifactState.CONFLICT || isVersionMismatch(mavenArtifactNode); + } + + static boolean isConflictAlternativeMethod(MavenArtifactNode mavenArtifactNode) { + return mavenArtifactNode.getState() != MavenArtifactState.ADDED && mavenArtifactNode.getState() != MavenArtifactState.EXCLUDED && !isVersionMatch(mavenArtifactNode); + } +}