From ebc9ca08206c60fed6d8d5eba5e1f5ad4c8ef70c Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 1 Mar 2016 13:22:26 +0100 Subject: [PATCH 01/23] + scale(int):int method --- platform/util/src/com/intellij/util/ui/EmptyIcon.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/platform/util/src/com/intellij/util/ui/EmptyIcon.java b/platform/util/src/com/intellij/util/ui/EmptyIcon.java index 2d08af300fdf..b77ddba23dfa 100644 --- a/platform/util/src/com/intellij/util/ui/EmptyIcon.java +++ b/platform/util/src/com/intellij/util/ui/EmptyIcon.java @@ -80,12 +80,12 @@ public class EmptyIcon implements Icon, ScalableIcon { @Override public int getIconWidth() { - return scale == 1f ? width : (int) (width * scale); + return scale(width); } @Override public int getIconHeight() { - return scale == 1f ? height : (int) (height * scale); + return scale(height); } @Override @@ -117,6 +117,10 @@ public class EmptyIcon implements Icon, ScalableIcon { return new EmptyIconUIResource(this); } + protected int scale(int n) { + return scale == 1f ? n : (int) (n * scale); + } + @Override public Icon scale(float scaleFactor) { if (scaleFactor != scale) { From 310ad3453d5777f5feaf8029147d6cff153394bf Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 1 Mar 2016 13:42:31 +0100 Subject: [PATCH 02/23] EmptyIcon: move scaled cache to parent --- .../src/com/intellij/util/ui/ColorIcon.java | 17 +++------- .../src/com/intellij/util/ui/EmptyIcon.java | 31 +++++++++++++------ 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/platform/util/src/com/intellij/util/ui/ColorIcon.java b/platform/util/src/com/intellij/util/ui/ColorIcon.java index 323a0a1433fb..9182dd4cc2bd 100644 --- a/platform/util/src/com/intellij/util/ui/ColorIcon.java +++ b/platform/util/src/com/intellij/util/ui/ColorIcon.java @@ -18,7 +18,6 @@ package com.intellij.util.ui; import com.intellij.ui.Gray; import org.jetbrains.annotations.NotNull; -import javax.swing.*; import java.awt.*; /** @@ -28,7 +27,6 @@ public class ColorIcon extends EmptyIcon { private final Color myColor; private boolean myBorder; private int myColorSize; - private ColorIcon myScaledCache; public ColorIcon(int size, int colorSize, @NotNull Color color, final boolean border) { super(size, size); @@ -68,20 +66,13 @@ public class ColorIcon extends EmptyIcon { } protected int getColorSize() { - return scale == 1f ? myColorSize : (int)(myColorSize * scale); + return scale(myColorSize); } + @Override - public Icon scale(float scaleFactor) { - if (scale == scaleFactor) { - return this; - } - if (myScaledCache != null && myScaledCache.scale == scaleFactor) { - return myScaledCache; - } - myScaledCache = new ColorIcon(getIconWidth(), myColorSize, myColor, myBorder); - myScaledCache.scale = scaleFactor; - return myScaledCache; + protected EmptyIcon createScaledInstance(float scale) { + return new ColorIcon(getIconWidth(), myColorSize, myColor, myBorder); } @Override diff --git a/platform/util/src/com/intellij/util/ui/EmptyIcon.java b/platform/util/src/com/intellij/util/ui/EmptyIcon.java index b77ddba23dfa..843eb9a08a05 100644 --- a/platform/util/src/com/intellij/util/ui/EmptyIcon.java +++ b/platform/util/src/com/intellij/util/ui/EmptyIcon.java @@ -42,6 +42,7 @@ public class EmptyIcon implements Icon, ScalableIcon { private final int width; private final int height; protected float scale = 1f; + private EmptyIcon myScaledCache; public static Icon create(int size) { Icon icon = cache.get(size); @@ -123,17 +124,27 @@ public class EmptyIcon implements Icon, ScalableIcon { @Override public Icon scale(float scaleFactor) { - if (scaleFactor != scale) { - EmptyIcon icon; - if (scale != 1f) { - icon = this; - } else { - icon = this instanceof UIResource ? new EmptyIconUIResource(width, height) : new EmptyIcon(width, height); - } - icon.scale = scaleFactor; - return icon; + if (scale == scaleFactor) { + return this; } - return this; + + if (myScaledCache != null && myScaledCache.scale == scaleFactor) { + return myScaledCache; + } + + myScaledCache = createScaledInstance(scaleFactor); + myScaledCache.scale = scaleFactor; + return myScaledCache; + } + + protected EmptyIcon createScaledInstance(float scale) { + final EmptyIcon icon; + if (scale != 1f) { + icon = this; + } else { + icon = this instanceof UIResource ? new EmptyIconUIResource(width, height) : new EmptyIcon(width, height); + } + return icon; } public static class EmptyIconUIResource extends EmptyIcon implements UIResource { From 86a732e0a882d606cfb2b73582a24f1d4c0ead17 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 1 Mar 2016 13:43:44 +0100 Subject: [PATCH 03/23] IDEA-152131 Color icons in editor gutter are replaced with empty icons when scaled --- .../com/intellij/util/ui/TwoColorsIcon.java | 57 ++++++++++++------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/platform/util/src/com/intellij/util/ui/TwoColorsIcon.java b/platform/util/src/com/intellij/util/ui/TwoColorsIcon.java index a6b1ed302c70..ad217324dad8 100644 --- a/platform/util/src/com/intellij/util/ui/TwoColorsIcon.java +++ b/platform/util/src/com/intellij/util/ui/TwoColorsIcon.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,9 @@ */ package com.intellij.util.ui; +import com.intellij.openapi.ui.GraphicsConfig; +import com.intellij.ui.Gray; +import com.intellij.ui.JBColor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -22,45 +25,59 @@ import java.awt.*; import java.awt.image.BufferedImage; /** - * User: Vassiliy.Kudryashov + * @author Vassiliy Kudryashov + * @author Konstantin Bulenkov */ -public class TwoColorsIcon extends EmptyIcon { - @NotNull private final Paint myColor1; - @NotNull private final Paint myColor2; - private static final int SQUARE_SIZE = 6; +public class TwoColorsIcon extends ColorIcon { + @NotNull private final Color mySecondColor; + private static final int SQUARE_SIZE = JBUI.scale(6); private static final BufferedImage CHESS_IMAGE = UIUtil.createImage(SQUARE_SIZE, SQUARE_SIZE, BufferedImage.TYPE_INT_RGB); + private static final TexturePaint CHESS; + static { Graphics2D graphics = CHESS_IMAGE.createGraphics(); graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); - graphics.setColor(Color.LIGHT_GRAY); + graphics.setColor(JBColor.LIGHT_GRAY); graphics.fillRect(0, 0, SQUARE_SIZE + 1, SQUARE_SIZE + 1); - graphics.setColor(Color.GRAY); + graphics.setColor(JBColor.GRAY); graphics.fillRect(0, 0, SQUARE_SIZE / 2, SQUARE_SIZE / 2); graphics.fillRect(SQUARE_SIZE / 2, SQUARE_SIZE / 2, SQUARE_SIZE / 2, SQUARE_SIZE / 2); + graphics.dispose(); + CHESS = new TexturePaint(CHESS_IMAGE, new Rectangle(0, 0, SQUARE_SIZE, SQUARE_SIZE)); } - private TexturePaint CHESS = new TexturePaint(CHESS_IMAGE, new Rectangle(0, 0, SQUARE_SIZE, SQUARE_SIZE)); - public TwoColorsIcon(int size, @Nullable Color color1, @Nullable Color color2) { - super(size, size); - myColor1 = color1 != null ? color1 : CHESS; - myColor2 = color2 != null ? color2 : CHESS; + public TwoColorsIcon(int size, @Nullable Color color1, @Nullable Color secondColor) { + super(size, size, color1 != null ? color1 : Gray.TRANSPARENT, false); + mySecondColor = secondColor != null ? secondColor : Gray.TRANSPARENT; } @Override - public void paintIcon(final Component component, final Graphics g, final int x, final int y) { + public void paintIcon(final Component component, Graphics g, int x, int y) { Graphics2D g2d = (Graphics2D)g.create(); + final GraphicsConfig config = GraphicsUtil.setupAAPainting(g2d); try { final int w = getIconWidth(); final int h = getIconHeight(); - GraphicsUtil.setupAAPainting(g2d); - g2d.setPaint(myColor1); + g2d.setPaint(getPaint(getIconColor())); g2d.fillPolygon(new int[]{x, x + w, x}, new int[]{y, y, y + h}, 3); - g2d.setPaint(myColor2); + g2d.setPaint(getPaint(mySecondColor)); g2d.fillPolygon(new int[]{x + w, x + w, x}, new int[]{y, y + h, y + h}, 3); } catch (Exception e) { g2d.dispose(); } + finally { + config.restore(); + } + } + + protected Paint getPaint(Color color) { + return color == null || color.getAlpha() == 0 ? CHESS : color; + } + + @Override + protected EmptyIcon createScaledInstance(float scale) { + return new TwoColorsIcon(getColorSize(), getIconColor(), mySecondColor); } @Override @@ -73,16 +90,14 @@ public class TwoColorsIcon extends EmptyIcon { if (getIconWidth() != icon.getIconWidth()) return false; if (getIconHeight() != icon.getIconHeight()) return false; - if (!myColor1.equals(icon.myColor1)) return false; - if (!myColor2.equals(icon.myColor2)) return false; + if (!mySecondColor.equals(icon.mySecondColor)) return false; return true; } @Override public int hashCode() { int result = super.hashCode(); - result = 31 * result + myColor1.hashCode(); - result = 31 * result + myColor2.hashCode(); + result = 31 * result + mySecondColor.hashCode(); return result; } } From 1a82302d4507bc5419add18414eafd057df0d5c9 Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Tue, 1 Mar 2016 15:50:32 +0300 Subject: [PATCH 04/23] IDEA-149210 Rework IDE notifications: move notification to bottom right side (EventLog) --- .../impl/NotificationsManagerImpl.java | 4 +-- .../intellij/openapi/wm/impl/IdeRootPane.java | 4 +++ .../openapi/wm/impl/ToolWindowsPane.java | 4 +++ .../com/intellij/ui/BalloonLayoutImpl.java | 27 ++++++++++++++++++- 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java b/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java index 08258bf238aa..f7cce06180ba 100644 --- a/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java @@ -81,7 +81,7 @@ public class NotificationsManagerImpl extends NotificationsManager { } public static boolean newEnabled() { - return Registry.is("ide.new.notification.enabled", false); + return ApplicationManager.getApplication().isInternal() && Registry.is("ide.new.notification.enabled", false); } @Override @@ -227,7 +227,7 @@ public class NotificationsManagerImpl extends NotificationsManager { final ProjectManager projectManager = ProjectManager.getInstance(); final boolean noProjects = projectManager.getOpenProjects().length == 0; final boolean sticky = NotificationDisplayType.STICKY_BALLOON == displayType || noProjects; - Ref layoutDataRef = newEnabled() && notification.getIcon() != null ? new Ref() : null; + Ref layoutDataRef = newEnabled() ? new Ref() : null; final Balloon balloon = createBalloon((IdeFrame)window, notification, false, false, layoutDataRef); Disposer.register(project != null ? project : ApplicationManager.getApplication(), balloon); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeRootPane.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeRootPane.java index c38b5e0fbab7..28eb294e86a5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeRootPane.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeRootPane.java @@ -298,6 +298,10 @@ public class IdeRootPane extends JRootPane implements UISettingsListener { return myStatusBar; } + public int getStatusBarHeight() { + return myStatusBar.isVisible() ? myStatusBar.getHeight() : 0; + } + private void updateToolbarVisibility(){ myToolbar.setVisible(myUISettings.SHOW_MAIN_TOOLBAR && !UISettings.getInstance().PRESENTATION_MODE); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowsPane.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowsPane.java index 49e26e75699c..c3628e977c7a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowsPane.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowsPane.java @@ -445,6 +445,10 @@ public final class ToolWindowsPane extends JBLayeredPane implements Disposable { } } + public int getBottomHeight() { + return myBottomStripe.isVisible() ? myBottomStripe.getHeight() : 0; + } + @Nullable Stripe getStripeFor(String id) { ToolWindow window = myManager.getToolWindow(id); diff --git a/platform/platform-impl/src/com/intellij/ui/BalloonLayoutImpl.java b/platform/platform-impl/src/com/intellij/ui/BalloonLayoutImpl.java index f2376c61e557..e789cac6fb09 100644 --- a/platform/platform-impl/src/com/intellij/ui/BalloonLayoutImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/BalloonLayoutImpl.java @@ -17,9 +17,11 @@ package com.intellij.ui; import com.intellij.ide.ui.LafManager; import com.intellij.ide.ui.LafManagerListener; +import com.intellij.notification.impl.NotificationsManagerImpl; import com.intellij.openapi.Disposable; import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.wm.impl.IdeRootPane; import com.intellij.openapi.wm.impl.ToolWindowsPane; import com.intellij.util.Alarm; import com.intellij.util.ui.JBInsets; @@ -162,7 +164,7 @@ public class BalloonLayoutImpl implements BalloonLayout { private void calculateSize() { myWidth = null; - if (myLayoutData.isEmpty()) { + if (myLayoutData.isEmpty() && !NotificationsManagerImpl.newEnabled()) { return; } @@ -199,6 +201,11 @@ public class BalloonLayoutImpl implements BalloonLayout { JComponent layeredPane = pane != null ? pane.getMyLayeredPane() : null; int eachColumnX = (layeredPane == null ? myLayeredPane.getWidth() : layeredPane.getX() + layeredPane.getWidth()) - 4; + if (NotificationsManagerImpl.newEnabled()) { + newLayout(columns.get(0), eachColumnX + 4, (int)myLayeredPane.getBounds().getMaxY()); + return; + } + if (myLayoutData.isEmpty()) { for (int i = 0; i < columns.size(); i++) { final ArrayList eachColumn = columns.get(i); @@ -282,6 +289,24 @@ public class BalloonLayoutImpl implements BalloonLayout { } } + private void newLayout(List balloons, int startX, int bottomY) { + int y = bottomY; + ToolWindowsPane pane = UIUtil.findComponentOfType(myParent, ToolWindowsPane.class); + if (pane != null) { + y -= pane.getBottomHeight(); + } + if (myParent instanceof IdeRootPane) { + y -= ((IdeRootPane)myParent).getStatusBarHeight(); + } + + for (Balloon balloon : balloons) { + Rectangle bounds = new Rectangle(getSize(balloon)); + y -= bounds.height; + bounds.setLocation(startX - bounds.width, y); + balloon.setBounds(bounds); + } + } + private List computeWidths(List> columns) { List columnWidths = new ArrayList(); for (ArrayList eachColumn : columns) { From ae71b78d2f52d9d25844691a41bfbdb549aecd3d Mon Sep 17 00:00:00 2001 From: Valentina Kiryushkina Date: Tue, 1 Mar 2016 16:02:32 +0300 Subject: [PATCH 05/23] Remove task status from studyStatusMap and taskStatusMap while getting --- .../jetbrains/edu/learning/StudyTaskManager.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyTaskManager.java b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyTaskManager.java index afd86b186c46..c8910edcccac 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyTaskManager.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyTaskManager.java @@ -126,16 +126,30 @@ public class StudyTaskManager implements PersistentStateComponent, Dumb StudyStatus taskFileStatus = getStatus(taskFile); if (taskFileStatus == StudyStatus.Unchecked) { task.setStatus(StudyStatus.Unchecked); + removeObsoleteTaskStatus(task); return StudyStatus.Unchecked; } if (taskFileStatus == StudyStatus.Failed) { task.setStatus(StudyStatus.Failed); + removeObsoleteTaskStatus(task); return StudyStatus.Failed; } } task.setStatus(StudyStatus.Solved); + removeObsoleteTaskStatus(task); return StudyStatus.Solved; } + + private void removeObsoleteTaskStatus(Task task) { + for (TaskFile taskFile: task.taskFiles.values()) { + myTaskStatusMap.remove(taskFile); + + for (AnswerPlaceholder answerPlaceholder: taskFile.getAnswerPlaceholders()) { + myStudyStatusMap.remove(answerPlaceholder); + } + } + + } private StudyStatus getStatus(@NotNull final TaskFile file) { if (file.getAnswerPlaceholders().isEmpty()) { From 6af729cb33614eb4f8bc420a4b9bc3b7e84e0d16 Mon Sep 17 00:00:00 2001 From: "Vladimir.Orlov" Date: Tue, 1 Mar 2016 16:21:47 +0300 Subject: [PATCH 06/23] IDEA-151997 Windows uninstaller should proceed to file deletion only if no IDE instances running --- build/conf/nsis/idea_en.nsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/conf/nsis/idea_en.nsi b/build/conf/nsis/idea_en.nsi index 1cb4408d1143..762514aef467 100644 --- a/build/conf/nsis/idea_en.nsi +++ b/build/conf/nsis/idea_en.nsi @@ -19,4 +19,4 @@ LangString uninstall_previous_installations_title ${LANG_ENGLISH} "Uninstall old LangString uninstall_previous_installations ${LANG_ENGLISH} "" LangString uninstall_previous_installations_prompt ${LANG_ENGLISH} "Select the ${MUI_PRODUCT} version$2 that you want to uninstall." LangString empty_or_upgrade_folder ${LANG_ENGLISH} "Please select an empty folder or a folder where ${MUI_PRODUCT} ${UPGRADE_VERSION} is installed as the target for installing ${MUI_PRODUCT}." -LangString application_running ${LANG_ENGLISH} "$3 is running. Close the application and retry the installation." +LangString application_running ${LANG_ENGLISH} "$INSTDIR is running. Close the application and retry the installation." From 2145921fb1206e440f32af2dc5f85fccae492f70 Mon Sep 17 00:00:00 2001 From: nik Date: Tue, 1 Mar 2016 16:28:17 +0300 Subject: [PATCH 07/23] attach sources to library: allow to add the chosen files as is if no sources are detected inside (KT-8592) --- .../roots/ui/configuration/PathUIUtils.java | 4 +- .../libraries/ui/impl/RootDetectionUtil.java | 42 +++++++++++++------ 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/PathUIUtils.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/PathUIUtils.java index f44643b92891..3bcb1c45792c 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/PathUIUtils.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/PathUIUtils.java @@ -41,7 +41,7 @@ public class PathUIUtils { /** * This method takes a candidates for the project root, then scans the candidates and - * if multiple candidates or non root source directories are found whithin some + * if multiple candidates or non root source directories are found within some * directories, it shows a dialog that allows selecting or deselecting them. * @param parent a parent parent or project * @param rootCandidates a candidates for roots @@ -50,7 +50,7 @@ public class PathUIUtils { public static VirtualFile[] scanAndSelectDetectedJavaSourceRoots(Component parentComponent, final VirtualFile[] rootCandidates) { final List orderRoots = RootDetectionUtil.detectRoots(Arrays.asList(rootCandidates), parentComponent, null, new LibraryRootsDetectorImpl(Arrays.asList(Extensions.getExtensions(RootDetector.JAVA_SOURCE_ROOT_DETECTOR))), - new OrderRootType[0]); + new OrderRootType[] {OrderRootType.SOURCES}); final List result = new ArrayList(); for (OrderRoot root : orderRoots) { result.add(root.getFile()); diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/RootDetectionUtil.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/RootDetectionUtil.java index c6493e7baafe..7de49054cff4 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/RootDetectionUtil.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/RootDetectionUtil.java @@ -28,6 +28,7 @@ import com.intellij.openapi.roots.libraries.ui.DetectedLibraryRoot; import com.intellij.openapi.roots.libraries.ui.LibraryRootsComponentDescriptor; import com.intellij.openapi.roots.libraries.ui.LibraryRootsDetector; import com.intellij.openapi.roots.libraries.ui.OrderRoot; +import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -119,20 +120,37 @@ public class RootDetectionUtil { } LOG.assertTrue(!types.isEmpty(), "No allowed root types found for " + detector); List names = new ArrayList(types.keySet()); - String title = "Choose Categories of Selected Files"; - String description = XmlStringUtil.wrapInHtml(ApplicationNamesInfo.getInstance().getProductName() + " cannot determine what kind of files the chosen items contain.
" + - "Choose the appropriate categories from the list."); - ChooseElementsDialog dialog; - if (parentComponent != null) { - dialog = new ChooseRootTypeElementsDialog(parentComponent, names, title, description); + if (names.size() == 1) { + String title = "Attach Roots"; + String typeName = names.get(0); + String message = ApplicationNamesInfo.getInstance().getProductName() + " cannot determine what kind of files the chosen items contain. " + + "Do you want to attach them as '" + typeName + "'?"; + int answer = parentComponent != null + ? Messages.showYesNoDialog(parentComponent, message, title, null) + : Messages.showYesNoDialog(project, message, title, null); + if (answer == Messages.YES) { + Pair pair = types.get(typeName); + for (VirtualFile candidate : rootCandidates) { + result.add(new OrderRoot(candidate, pair.getFirst(), pair.getSecond())); + } + } } else { - dialog = new ChooseRootTypeElementsDialog(project, names, title, description); - } - for (String rootType : dialog.showAndGetResult()) { - final Pair pair = types.get(rootType); - for (VirtualFile candidate : rootCandidates) { - result.add(new OrderRoot(candidate, pair.getFirst(), pair.getSecond())); + String title = "Choose Categories of Selected Files"; + String description = XmlStringUtil.wrapInHtml(ApplicationNamesInfo.getInstance().getProductName() + " cannot determine what kind of files the chosen items contain.
" + + "Choose the appropriate categories from the list."); + ChooseElementsDialog dialog; + if (parentComponent != null) { + dialog = new ChooseRootTypeElementsDialog(parentComponent, names, title, description); + } + else { + dialog = new ChooseRootTypeElementsDialog(project, names, title, description); + } + for (String rootType : dialog.showAndGetResult()) { + final Pair pair = types.get(rootType); + for (VirtualFile candidate : rootCandidates) { + result.add(new OrderRoot(candidate, pair.getFirst(), pair.getSecond())); + } } } } From c450fedc6f556c9f46dc8be36a7a54ceb1f24878 Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Mon, 29 Feb 2016 18:41:54 +0300 Subject: [PATCH 08/23] IDEA-152156 Test --- .../impl/EditorColorsSchemeImplTest.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java index 81029fb59ccb..238c931f85a5 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java @@ -20,6 +20,7 @@ import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.FontPreferences; import com.intellij.openapi.editor.colors.TextAttributesKey; +import com.intellij.openapi.editor.markup.EffectType; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.WriteExternalException; @@ -290,6 +291,37 @@ public class EditorColorsSchemeImplTest extends LightPlatformCodeInsightTestCase } } + + @SuppressWarnings("unused") + public void _testIdea152156() throws Exception { + EditorColorsScheme defaultScheme = EditorColorsManager.getInstance().getScheme(EditorColorsScheme.DEFAULT_SCHEME_NAME); + EditorColorsScheme parentScheme = (EditorColorsScheme)defaultScheme.clone(); + parentScheme.setName("DefaultTest"); + EditorColorsScheme editorColorsScheme = new EditorColorsSchemeImpl(parentScheme); + editorColorsScheme.setName("test"); + TextAttributes defaultAttributes = new TextAttributes(null, null, Color.BLACK, EffectType.LINE_UNDERSCORE, Font.PLAIN); + TextAttributes attributes = new TextAttributes(null, null, null, EffectType.BOXED, Font.PLAIN); + attributes.setEnforceEmpty(false); + assertTrue(attributes.isFallbackEnabled()); + TextAttributesKey testKey = TextAttributesKey.createTextAttributesKey("TEST_KEY", DefaultLanguageHighlighterColors.PARAMETER); + parentScheme.setAttributes(testKey, defaultAttributes); + editorColorsScheme.setAttributes(testKey, attributes); + try { + Element root = new Element("scheme"); + ((AbstractColorsScheme)editorColorsScheme).writeExternal(root); + EditorColorsScheme targetScheme = new EditorColorsSchemeImpl(parentScheme); + for (final Element child : root.getChildren()) { + if ("attributes".equals(child.getName())) { + ((EditorColorsSchemeImpl)targetScheme).readAttributes(child); + } + } + TextAttributes targetAttributes = ((AbstractColorsScheme)targetScheme).getDirectlyDefinedAttributes(testKey); + assertTrue(targetAttributes != null && targetAttributes.isFallbackEnabled()); + } + finally { + TextAttributesKey.removeTextAttributesKey(testKey.getExternalName()); + } + } private static EditorColorsScheme loadScheme(@NotNull String docText) throws ParserConfigurationException, IOException, SAXException { From 89dcde70dde36e9426961268de9035895e0ebcd4 Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Mon, 29 Feb 2016 19:01:47 +0300 Subject: [PATCH 09/23] Cleanup --- .../editor/colors/impl/EditorColorsSchemeImplTest.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java index 238c931f85a5..2006051a53f4 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java @@ -46,20 +46,21 @@ import java.util.Collections; import static com.intellij.openapi.editor.colors.FontPreferencesTest.*; import static java.util.Collections.singletonList; +@SuppressWarnings("Duplicates") public class EditorColorsSchemeImplTest extends LightPlatformCodeInsightTestCase { EditorColorsSchemeImpl myScheme = new EditorColorsSchemeImpl(null); public void testDefaults() { checkState(myScheme.getFontPreferences(), - Collections.emptyList(), - Collections.emptyList(), + Collections.emptyList(), + Collections.emptyList(), FontPreferences.DEFAULT_FONT_NAME, FontPreferences.DEFAULT_FONT_NAME, null); assertEquals(FontPreferences.DEFAULT_FONT_NAME, myScheme.getEditorFontName()); assertEquals(FontPreferences.DEFAULT_FONT_SIZE, myScheme.getEditorFontSize()); checkState(myScheme.getConsoleFontPreferences(), - Collections.emptyList(), - Collections.emptyList(), + Collections.emptyList(), + Collections.emptyList(), FontPreferences.DEFAULT_FONT_NAME, FontPreferences.DEFAULT_FONT_NAME, null); assertEquals(FontPreferences.DEFAULT_FONT_NAME, myScheme.getConsoleFontName()); From c5ea70c7ff0979b360fe256e85a4d5071a83fb14 Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Tue, 1 Mar 2016 16:21:53 +0300 Subject: [PATCH 10/23] FIXED IDEA-152156 Unable to save new colors for old existing theme --- .../editor/colors/impl/AbstractColorsScheme.java | 11 ++++++++++- .../colors/impl/EditorColorsSchemeImplTest.java | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java index 21aba543141b..530fbfc2962a 100644 --- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java +++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java @@ -606,7 +606,7 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { Element element = new Element(OPTION_ELEMENT); element.setAttribute(NAME_ATTR, key.getExternalName()); if (baseKey != null && value.isFallbackEnabled()) { - if (defaultFallbackAttr != null && defaultAttr != null && defaultAttr != defaultFallbackAttr) { + if (isParentOverwritingInheritance(key)) { element.setAttribute(BASE_ATTRIBUTES_ATTR, baseKey.getExternalName()); attrElements.addContent(element); } @@ -622,6 +622,15 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { } } + private boolean isParentOverwritingInheritance(@NotNull TextAttributesKey key) { + TextAttributes parentAttrs = + myParentScheme instanceof AbstractColorsScheme ? ((AbstractColorsScheme)myParentScheme).getDirectlyDefinedAttributes(key) : null; + if (parentAttrs != null) { + return !parentAttrs.isFallbackEnabled(); + } + return false; + } + protected Color getOwnColor(ColorKey key) { return myColorsMap.get(key); } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java index 2006051a53f4..87f159200272 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java @@ -294,7 +294,7 @@ public class EditorColorsSchemeImplTest extends LightPlatformCodeInsightTestCase } @SuppressWarnings("unused") - public void _testIdea152156() throws Exception { + public void testIdea152156() throws Exception { EditorColorsScheme defaultScheme = EditorColorsManager.getInstance().getScheme(EditorColorsScheme.DEFAULT_SCHEME_NAME); EditorColorsScheme parentScheme = (EditorColorsScheme)defaultScheme.clone(); parentScheme.setName("DefaultTest"); From 5673683e95f7d048b8ad47ea7b3d673a22b375bb Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 1 Mar 2016 14:09:53 +0100 Subject: [PATCH 11/23] extract method suggester: unique parameter names (IDEA-152334); update output variables when suggester replaces the initial method --- .../extractMethod/ExtractMethodProcessor.java | 16 ++++++++++ .../ExtractMethodSignatureSuggester.java | 6 ++++ ...estChangeSignatureWithOutputVariables.java | 25 ++++++++++++++++ ...ngeSignatureWithOutputVariables_after.java | 29 +++++++++++++++++++ .../refactoring/ExtractMethodTest.java | 4 +++ 5 files changed, 80 insertions(+) create mode 100644 java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureWithOutputVariables.java create mode 100644 java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureWithOutputVariables_after.java diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java index 570d4d57f563..0368e04bfa49 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java @@ -1728,6 +1728,22 @@ public class ExtractMethodProcessor implements MatchProvider { myExtractedMethod = suggester.getExtractedMethod(); myMethodCall = suggester.getMethodCall(); myVariableDatum = suggester.getVariableData(); + + final List outputVariables = new ArrayList<>(); + for (PsiReturnStatement statement : PsiUtil.findReturnStatements(myExtractedMethod)) { + final PsiExpression returnValue = statement.getReturnValue(); + if (returnValue instanceof PsiReferenceExpression) { + final PsiElement resolve = ((PsiReferenceExpression)returnValue).resolve(); + if (resolve instanceof PsiLocalVariable) { + outputVariables.add((PsiVariable)resolve); + } + } + } + + if (outputVariables.size() == 1) { + myOutputVariable = outputVariables.get(0); + } + return null; } } diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodSignatureSuggester.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodSignatureSuggester.java index ceac680e7c47..0748b6f83351 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodSignatureSuggester.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodSignatureSuggester.java @@ -334,6 +334,12 @@ public class ExtractMethodSignatureSuggester { for (PsiParameter parameter : parameters) { uniqueNameGenerator.addExistingName(parameter.getName()); } + + SyntaxTraverser.psiTraverser().withRoot(myExtractedMethod.getBody()) + .filter(element -> element instanceof PsiVariable) + .forEach(element -> uniqueNameGenerator.addExistingName(((PsiVariable)element).getName())); + + final THashMap unique = new THashMap(ourEquivalenceStrategy); final Map replacement = new HashMap(); for (PsiExpression expr : exprs) { diff --git a/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureWithOutputVariables.java b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureWithOutputVariables.java new file mode 100644 index 000000000000..d2d648133430 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureWithOutputVariables.java @@ -0,0 +1,25 @@ + +class Test { + + private BigDecimal getRevenue() { + final String query = createNamedQuery("revenues"); + String revenues = ""; + final String revenue; + revenue = "a"; + + return revenue; + } + + public BigDecimal getExpense() { + final String query = createNamedQuery("expenses"); + String expenses = ""; + final String expense; + expense = "a"; + + return expense; + } + + private String createNamedQuery(String expenses) { + return null; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureWithOutputVariables_after.java b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureWithOutputVariables_after.java new file mode 100644 index 000000000000..2397db581d4c --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureWithOutputVariables_after.java @@ -0,0 +1,29 @@ +import org.jetbrains.annotations.NotNull; + +class Test { + + private BigDecimal getRevenue() { + final String revenue = newMethod("revenues"); + + return revenue; + } + + @NotNull + private String newMethod(String revenues2) { + final String query = createNamedQuery(revenues2); + String revenues = ""; + final String revenue; + revenue = "a"; + return revenue; + } + + public BigDecimal getExpense() { + final String expense = newMethod("expenses"); + + return expense; + } + + private String createNamedQuery(String expenses) { + return null; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java index 27032f4532cf..650badbd68c0 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java @@ -675,6 +675,10 @@ public class ExtractMethodTest extends LightCodeInsightTestCase { doDuplicatesTest(); } + public void testSuggestChangeSignatureWithOutputVariables() throws Exception { + doDuplicatesTest(); + } + public void testSuggestChangeSignatureWithChangedParameterName() throws Exception { configureByFile(BASE_PATH + getTestName(false) + ".java"); boolean success = performExtractMethod(true, true, getEditor(), getFile(), getProject(), false, null, false, "p"); From 4e35c9f627139703c495c4ce59a193cf1d9ca456 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Tue, 1 Mar 2016 17:27:09 +0300 Subject: [PATCH 12/23] do not make variants from case-sensitive file references case-insensitive (WEB-10645) --- .../codeInsight/completion/HtmlCompletionData.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/xml/impl/src/com/intellij/codeInsight/completion/HtmlCompletionData.java b/xml/impl/src/com/intellij/codeInsight/completion/HtmlCompletionData.java index ab1c1e1c218b..7bb515438bfc 100644 --- a/xml/impl/src/com/intellij/codeInsight/completion/HtmlCompletionData.java +++ b/xml/impl/src/com/intellij/codeInsight/completion/HtmlCompletionData.java @@ -18,6 +18,7 @@ package com.intellij.codeInsight.completion; import com.intellij.lang.Language; import com.intellij.openapi.util.Comparing; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiReference; import com.intellij.psi.filters.AndFilter; import com.intellij.psi.filters.ElementFilter; import com.intellij.psi.filters.OrFilter; @@ -25,6 +26,7 @@ import com.intellij.psi.filters.TextContainFilter; import com.intellij.psi.filters.getters.HtmlAttributeValueGetter; import com.intellij.psi.filters.getters.XmlAttributeValueGetter; import com.intellij.psi.filters.position.XmlTokenTypeFilter; +import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.xml.XmlAttribute; import com.intellij.psi.xml.XmlTag; @@ -136,7 +138,8 @@ public class HtmlCompletionData extends XmlCompletionData { @Override public boolean isAcceptable(Object element, PsiElement context) { if (isStyleAttributeContext(context)) return false; - if ( isScriptContext((PsiElement)element) ) return false; + if (isScriptContext((PsiElement)element)) return false; + if (hasCaseSensitiveFileReferences(context)) return false; return true; } @@ -147,6 +150,13 @@ public class HtmlCompletionData extends XmlCompletionData { }; } + private static boolean hasCaseSensitiveFileReferences(PsiElement context) { + for (PsiReference reference : context.getReferences()) { + if (reference instanceof FileReference && ((FileReference)reference).getFileReferenceSet().isCaseSensitive()) return true; + } + return false; + } + private static boolean isScriptContext(PsiElement element) { final Language language = element.getLanguage(); From 7657388e31fdc2f8f4d5d1647773d539a018b67e Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Tue, 1 Mar 2016 17:31:12 +0300 Subject: [PATCH 13/23] inspection tool window: hide suppress button if no suppress actions are available --- .../src/com/intellij/codeInspection/ui/QuickFixToolbar.java | 4 +++- .../com/intellij/openapi/actionSystem/ex/ComboBoxAction.java | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/QuickFixToolbar.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/QuickFixToolbar.java index d178b8e5ebb6..a50ffe72f5f0 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/QuickFixToolbar.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/QuickFixToolbar.java @@ -86,16 +86,18 @@ public class QuickFixToolbar extends JPanel { @NotNull final TreePath[] paths, @NotNull final Project project, boolean multipleDescriptors) { + final AnAction[] suppressors = new SuppressActionWrapper(project, toolWrapper, paths).getChildren(null); final ComboBoxAction action = new ComboBoxAction() { { getTemplatePresentation().setText(multipleDescriptors ? "Suppress All" : "Suppress"); + getTemplatePresentation().setEnabledAndVisible(suppressors.length != 0); } @NotNull @Override protected DefaultActionGroup createPopupActionGroup(JComponent button) { DefaultActionGroup group = new DefaultActionGroup(); - group.addAll(new SuppressActionWrapper(project, toolWrapper, paths).getChildren(null)); + group.addAll(suppressors); return group; } }; diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java index 1f6e017c529f..f6056927ebaa 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java @@ -147,8 +147,9 @@ public abstract class ComboBoxAction extends AnAction implements CustomComponent public ComboBoxButton(Presentation presentation) { myPresentation = presentation; - setEnabled(myPresentation.isEnabled()); setModel(new MyButtonModel()); + getModel().setEnabled(myPresentation.isEnabled()); + setVisible(presentation.isVisible()); setHorizontalAlignment(LEFT); setFocusable(false); if (isSmallVariant()) { From d530531cbed56fdab3789fc5f3e8cfdaa36658da Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Mon, 29 Feb 2016 19:06:49 +0300 Subject: [PATCH 14/23] vcs: display commit message in the successful commit notification The fix to IDEA-151547 removed the commit message from notification, but it is useful to have it there. --- .../src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java index d45f1d15807c..e170665fe41f 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java @@ -202,6 +202,9 @@ public class CommitHelper { @NotNull private String getCommitSummary(@NotNull GeneralCommitProcessor processor) { StringBuilder content = new StringBuilder(getFileSummaryReport(processor.getChangesFailedToCommit())); + if (!StringUtil.isEmpty(myCommitMessage)) { + content.append(": ").append(escape(myCommitMessage)); + } if (!myFeedback.isEmpty()) { content.append("
"); content.append(StringUtil.join(myFeedback, "
")); From 8ffa4c9a1386275cc83e08a9be085d3b24981b52 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 1 Mar 2016 17:31:43 +0300 Subject: [PATCH 15/23] vcs: fix EDT access The fix to IDEA-151547 made the proposal to move failed changes to another list be shown not from the EDT, leading to assertion. --- .../openapi/vcs/changes/ui/CommitHelper.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java index e170665fe41f..9610ec4cca0d 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java @@ -47,8 +47,8 @@ import com.intellij.util.NullableFunction; import com.intellij.util.WaitForProgressToShow; import com.intellij.util.concurrency.Semaphore; import com.intellij.util.ui.ConfirmationDialog; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.*; +import org.jetbrains.annotations.CalledInAwt; import java.util.ArrayList; import java.util.Collection; @@ -446,8 +446,13 @@ public class CommitHelper { } public void afterFailedCheckIn() { - moveToFailedList(myChangeList, myCommitMessage, getChangesFailedToCommit(), - VcsBundle.message("commit.dialog.failed.commit.template", myChangeList.getName()), myProject); + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + moveToFailedList(myChangeList, myCommitMessage, getChangesFailedToCommit(), + VcsBundle.message("commit.dialog.failed.commit.template", myChangeList.getName()), myProject); + } + }); } public void doBeforeRefresh() { @@ -629,6 +634,7 @@ public class CommitHelper { } } + @CalledInAwt public static void moveToFailedList(final ChangeList changeList, final String commitMessage, final List failedChanges, From ff65bb13fb2879119f16b4b6b84e7e9f1bd30a9d Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 1 Mar 2016 17:34:41 +0300 Subject: [PATCH 16/23] vcs: don't open Messages toolwindow to show commit message error it is already shown in the notification --- .../src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java index 9610ec4cca0d..9a1376b7cda7 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java @@ -272,8 +272,6 @@ public class CommitHelper { } processor.doBeforeRefresh(); - - AbstractVcsHelper.getInstance(myProject).showErrors(processor.getVcsExceptions(), myActionName); } catch (ProcessCanceledException pce) { throw pce; From 199793080287963eeafc2ddeb6fa0901e0843fb8 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Tue, 1 Mar 2016 16:19:42 +0300 Subject: [PATCH 17/23] Incorrect plugin groups for javaee (patch by Serega Vasiliev) (cherry picked from commit 3fbffbb) --- .../src/com/intellij/ide/customize/PluginGroups.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/customize/PluginGroups.java b/platform/platform-impl/src/com/intellij/ide/customize/PluginGroups.java index 6bf381304711..0a4e5f55e4da 100644 --- a/platform/platform-impl/src/com/intellij/ide/customize/PluginGroups.java +++ b/platform/platform-impl/src/com/intellij/ide/customize/PluginGroups.java @@ -121,14 +121,14 @@ public class PluginGroups { "com.intellij.spring," + "com.intellij.spring.webflow," + "com.intellij.spring.ws,com.intellij.aop", - "J2EE:com.intellij.javaee.batch," + + "Java EE:com.intellij.javaee.batch," + "com.intellij.beanValidation," + "com.intellij.cdi," + "com.intellij.javaee," + "com.intellij.jsf," + "com.intellij.javaee.extensions," + "com.jetbrains.restWebServices," + - "Java EE: Web Services (JAX-WS)," + + "Web Services (JAX-WS)," + "com.intellij.javaee.webSocket," + "com.intellij.jsp," + "com.intellij.persistence", From 87fefb067e1221d88d400212d044235a20cee6c0 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 1 Mar 2016 15:57:42 +0100 Subject: [PATCH 18/23] refactor API for Java source root detection in libraries (IDEA-CR-8732) --- .../daemon/impl/AttachSourcesNotificationProvider.java | 4 ++-- .../intellij/jarFinder/InternetAttachSourceProvider.java | 4 ++-- ...tDetector.java => LibraryJavaSourceRootDetector.java} | 4 ++-- ...thUIUtils.java => LibrarySourceRootDetectorUtil.java} | 9 +++++---- .../DefaultLibraryRootsComponentDescriptor.java | 3 ++- .../libraryEditor/SourcesOrderRootTypeUIFactory.java | 4 ++-- .../openapi/roots/libraries/ui/RootDetector.java | 2 -- resources/src/META-INF/IdeaPlugin.xml | 2 +- 8 files changed, 16 insertions(+), 16 deletions(-) rename java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/{JavaSourceRootDetector.java => LibraryJavaSourceRootDetector.java} (92%) rename java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/{PathUIUtils.java => LibrarySourceRootDetectorUtil.java} (87%) diff --git a/java/idea-ui/src/com/intellij/codeInsight/daemon/impl/AttachSourcesNotificationProvider.java b/java/idea-ui/src/com/intellij/codeInsight/daemon/impl/AttachSourcesNotificationProvider.java index 23a85aa41e57..ebac72fdd5bb 100644 --- a/java/idea-ui/src/com/intellij/codeInsight/daemon/impl/AttachSourcesNotificationProvider.java +++ b/java/idea-ui/src/com/intellij/codeInsight/daemon/impl/AttachSourcesNotificationProvider.java @@ -35,7 +35,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.roots.*; import com.intellij.openapi.roots.libraries.Library; -import com.intellij.openapi.roots.ui.configuration.PathUIUtils; +import com.intellij.openapi.roots.ui.configuration.LibrarySourceRootDetectorUtil; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.ListSeparator; @@ -305,7 +305,7 @@ public class AttachSourcesNotificationProvider extends EditorNotifications.Provi Library firstLibrary = libraries.get(0).getLibrary(); VirtualFile[] roots = firstLibrary != null ? firstLibrary.getFiles(OrderRootType.CLASSES) : VirtualFile.EMPTY_ARRAY; VirtualFile[] candidates = FileChooser.chooseFiles(descriptor, myProject, roots.length == 0 ? null : PathUtil.getLocalFile(roots[0])); - final VirtualFile[] files = PathUIUtils.scanAndSelectDetectedJavaSourceRoots(myParentComponent, candidates); + final VirtualFile[] files = LibrarySourceRootDetectorUtil.scanAndSelectDetectedJavaSourceRoots(myParentComponent, candidates); if (files.length == 0) { return ActionCallback.REJECTED; } diff --git a/java/idea-ui/src/com/intellij/jarFinder/InternetAttachSourceProvider.java b/java/idea-ui/src/com/intellij/jarFinder/InternetAttachSourceProvider.java index 8ee9e96245c0..f17b29a4d0b0 100644 --- a/java/idea-ui/src/com/intellij/jarFinder/InternetAttachSourceProvider.java +++ b/java/idea-ui/src/com/intellij/jarFinder/InternetAttachSourceProvider.java @@ -26,7 +26,7 @@ import com.intellij.openapi.progress.Task; import com.intellij.openapi.roots.LibraryOrderEntry; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.libraries.Library; -import com.intellij.openapi.roots.ui.configuration.PathUIUtils; +import com.intellij.openapi.roots.ui.configuration.LibrarySourceRootDetectorUtil; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.JarFileSystem; @@ -215,7 +215,7 @@ public class InternetAttachSourceProvider implements AttachSourcesProvider { VirtualFile jarRoot = JarFileSystem.getInstance().getJarRootForLocalFile(srcFile); if (jarRoot == null) return; - VirtualFile[] roots = PathUIUtils.scanAndSelectDetectedJavaSourceRoots(null, new VirtualFile[]{jarRoot}); + VirtualFile[] roots = LibrarySourceRootDetectorUtil.scanAndSelectDetectedJavaSourceRoots(null, new VirtualFile[]{jarRoot}); if (roots.length == 0) { roots = new VirtualFile[]{jarRoot}; } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaSourceRootDetector.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/LibraryJavaSourceRootDetector.java similarity index 92% rename from java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaSourceRootDetector.java rename to java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/LibraryJavaSourceRootDetector.java index 3b02e0cd0fb7..f96d8e0667ad 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaSourceRootDetector.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/LibraryJavaSourceRootDetector.java @@ -23,8 +23,8 @@ import org.jetbrains.annotations.NotNull; import java.util.Collection; -public class JavaSourceRootDetector extends RootDetector { - public JavaSourceRootDetector() { +public class LibraryJavaSourceRootDetector extends RootDetector { + public LibraryJavaSourceRootDetector() { super(OrderRootType.SOURCES, false, "sources"); } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/PathUIUtils.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/LibrarySourceRootDetectorUtil.java similarity index 87% rename from java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/PathUIUtils.java rename to java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/LibrarySourceRootDetectorUtil.java index 3bcb1c45792c..6c310c35dc71 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/PathUIUtils.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/LibrarySourceRootDetectorUtil.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.roots.ui.configuration; +import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.libraries.ui.OrderRoot; @@ -33,10 +34,10 @@ import java.util.List; * * @author Constantine.Plotnikov */ -public class PathUIUtils { - public static final RootDetector JAVA_SOURCE_ROOT_DETECTOR = new JavaSourceRootDetector(); +public class LibrarySourceRootDetectorUtil { + public static ExtensionPointName JAVA_SOURCE_ROOT_DETECTOR = ExtensionPointName.create("com.intellij.library.javaSourceRootDetector"); - private PathUIUtils() { + private LibrarySourceRootDetectorUtil() { } /** @@ -49,7 +50,7 @@ public class PathUIUtils { */ public static VirtualFile[] scanAndSelectDetectedJavaSourceRoots(Component parentComponent, final VirtualFile[] rootCandidates) { final List orderRoots = RootDetectionUtil.detectRoots(Arrays.asList(rootCandidates), parentComponent, null, - new LibraryRootsDetectorImpl(Arrays.asList(Extensions.getExtensions(RootDetector.JAVA_SOURCE_ROOT_DETECTOR))), + new LibraryRootsDetectorImpl(Arrays.asList(Extensions.getExtensions(JAVA_SOURCE_ROOT_DETECTOR))), new OrderRootType[] {OrderRootType.SOURCES}); final List result = new ArrayList(); for (OrderRoot root : orderRoots) { diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/DefaultLibraryRootsComponentDescriptor.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/DefaultLibraryRootsComponentDescriptor.java index 3d7f31772362..a574f956e0ba 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/DefaultLibraryRootsComponentDescriptor.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/DefaultLibraryRootsComponentDescriptor.java @@ -30,6 +30,7 @@ import com.intellij.openapi.roots.NativeLibraryOrderRootType; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.libraries.ui.*; import com.intellij.openapi.roots.ui.OrderRootTypeUIFactory; +import com.intellij.openapi.roots.ui.configuration.LibrarySourceRootDetectorUtil; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; @@ -73,7 +74,7 @@ public class DefaultLibraryRootsComponentDescriptor extends LibraryRootsComponen List results = new ArrayList<>(); results.add(new FileTypeBasedRootFilter(OrderRootType.CLASSES, false, StdFileTypes.CLASS, "classes")); results.add(new FileTypeBasedRootFilter(OrderRootType.CLASSES, true, StdFileTypes.CLASS, "jar directory")); - results.addAll(Arrays.asList(Extensions.getExtensions(RootDetector.JAVA_SOURCE_ROOT_DETECTOR))); + results.addAll(Arrays.asList(Extensions.getExtensions(LibrarySourceRootDetectorUtil.JAVA_SOURCE_ROOT_DETECTOR))); Collections.addAll(results, new FileTypeBasedRootFilter(OrderRootType.SOURCES, true, StdFileTypes.JAVA, "source archive directory"), new JavadocRootDetector(), diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/SourcesOrderRootTypeUIFactory.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/SourcesOrderRootTypeUIFactory.java index 7bd294d5c4b3..8ed9e5c1efac 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/SourcesOrderRootTypeUIFactory.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/SourcesOrderRootTypeUIFactory.java @@ -23,7 +23,7 @@ import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.ui.SdkPathEditor; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.ui.OrderRootTypeUIFactory; -import com.intellij.openapi.roots.ui.configuration.PathUIUtils; +import com.intellij.openapi.roots.ui.configuration.LibrarySourceRootDetectorUtil; import com.intellij.openapi.vfs.VirtualFile; import javax.swing.*; @@ -61,7 +61,7 @@ public class SourcesOrderRootTypeUIFactory implements OrderRootTypeUIFactory { @Override protected VirtualFile[] adjustAddedFileSet(final Component component, final VirtualFile[] files) { if (mySdk.getSdkType() instanceof JavaSdkType) { - return PathUIUtils.scanAndSelectDetectedJavaSourceRoots(component, files); + return LibrarySourceRootDetectorUtil.scanAndSelectDetectedJavaSourceRoots(component, files); } return super.adjustAddedFileSet(component, files); } diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/RootDetector.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/RootDetector.java index 48f01c80feb8..14aa9321f7bc 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/RootDetector.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/RootDetector.java @@ -62,6 +62,4 @@ public abstract class RootDetector { */ @NotNull public abstract Collection detectRoots(@NotNull VirtualFile rootCandidate, @NotNull ProgressIndicator progressIndicator); - - public static ExtensionPointName JAVA_SOURCE_ROOT_DETECTOR = ExtensionPointName.create("com.intellij.library.javaSourceRootDetector"); } diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index ac9cb8fc667a..12dc68c04b4a 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -1725,7 +1725,7 @@ - + From e4205acc0bb555c6fa13b3cf4f02f85184456de3 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 1 Mar 2016 18:04:29 +0300 Subject: [PATCH 19/23] IDEA-151950 Decompiler doesn't work for classes from JDK 9 - support java 9 string concatenation --- .../decompiler/ConcatenationHelper.java | 69 ++++++++++++++++-- .../modules/decompiler/ExprProcessor.java | 13 +--- .../decompiler/exps/InvocationExprent.java | 35 ++++++--- .../java/decompiler/SingleClassesTest.java | 4 +- .../classes/java9/TestJava9StringConcat.class | Bin 0 -> 871 bytes .../classes/pkg/TestStringConcat.class | Bin 0 -> 740 bytes .../results/TestJava9StringConcat.dec | 27 +++++++ .../testData/results/TestStringConcat.dec | 31 ++++++++ .../src/java9/TestJava9StringConcat.java | 26 +++++++ .../testData/src/pkg/TestStringConcat.class | Bin 0 -> 740 bytes .../testData/src/pkg/TestStringConcat.java | 26 +++++++ 11 files changed, 206 insertions(+), 25 deletions(-) create mode 100644 plugins/java-decompiler/engine/testData/classes/java9/TestJava9StringConcat.class create mode 100644 plugins/java-decompiler/engine/testData/classes/pkg/TestStringConcat.class create mode 100644 plugins/java-decompiler/engine/testData/results/TestJava9StringConcat.dec create mode 100644 plugins/java-decompiler/engine/testData/results/TestStringConcat.dec create mode 100644 plugins/java-decompiler/engine/testData/src/java9/TestJava9StringConcat.java create mode 100644 plugins/java-decompiler/engine/testData/src/pkg/TestStringConcat.class create mode 100644 plugins/java-decompiler/engine/testData/src/pkg/TestStringConcat.java diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/ConcatenationHelper.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/ConcatenationHelper.java index 74ef0a2975f1..7d7b33d3864e 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/ConcatenationHelper.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/ConcatenationHelper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,11 +17,15 @@ package org.jetbrains.java.decompiler.modules.decompiler; import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.modules.decompiler.exps.*; +import org.jetbrains.java.decompiler.struct.consts.PooledConstant; +import org.jetbrains.java.decompiler.struct.consts.PrimitiveConstant; import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor; import org.jetbrains.java.decompiler.struct.gen.VarType; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.Set; public class ConcatenationHelper { @@ -52,6 +56,12 @@ public class ConcatenationHelper { exprTmp = iex.getInstance(); } } + else if ("makeConcatWithConstants".equals(iex.getName())) { // java 9 style + List parameters = extractParameters(iex.getBootstrapArguments(), iex); + if (parameters.size() >= 2) { + return createConcatExprent(parameters, expr.bytecode); + } + } } if (exprTmp == null) { @@ -125,20 +135,69 @@ public class ConcatenationHelper { lstOperands.set(i, rep); } } + return createConcatExprent(lstOperands, expr.bytecode); + } + private static Exprent createConcatExprent(List lstOperands, Set bytecode) { // build exprent to return Exprent func = lstOperands.get(0); for (int i = 1; i < lstOperands.size(); i++) { - List lstTmp = new ArrayList(); - lstTmp.add(func); - lstTmp.add(lstOperands.get(i)); - func = new FunctionExprent(FunctionExprent.FUNCTION_STR_CONCAT, lstTmp, expr.bytecode); + func = new FunctionExprent(FunctionExprent.FUNCTION_STR_CONCAT, Arrays.asList(func, lstOperands.get(i)), bytecode); } return func; } + // See StringConcatFactory in jdk sources + private static final char TAG_ARG = '\u0001'; + private static final char TAG_CONST = '\u0002'; + + private static List extractParameters(List bootstrapArguments, InvocationExprent expr) { + List parameters = expr.getLstParameters(); + if (bootstrapArguments != null) { + PooledConstant constant = bootstrapArguments.get(0); + if (constant.type == CodeConstants.CONSTANT_String) { + String recipe = ((PrimitiveConstant)constant).getString(); + + List res = new ArrayList<>(); + StringBuilder acc = new StringBuilder(); + int parameterId = 0; + for (int i = 0; i < recipe.length(); i++) { + char c = recipe.charAt(i); + + if (c == TAG_CONST || c == TAG_ARG) { + // Detected a special tag, flush all accumulated characters + // as a constant first: + if (acc.length() > 0) { + res.add(new ConstExprent(VarType.VARTYPE_STRING, acc.toString(), expr.bytecode)); + acc.setLength(0); + } + if (c == TAG_CONST) { + // skip for now + } + if (c == TAG_ARG) { + res.add(parameters.get(parameterId++)); + } + } + else { + // Not a special characters, this is a constant embedded into + // the recipe itself. + acc.append(c); + } + } + + // Flush the remaining characters as constant: + if (acc.length() > 0) { + res.add(new ConstExprent(VarType.VARTYPE_STRING, acc.toString(), expr.bytecode)); + } + + return res; + } + } + return new ArrayList<>(parameters); + } + private static boolean isAppendConcat(InvocationExprent expr, VarType cltype) { if ("append".equals(expr.getName())) { diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java index cbc66c78c63a..008d0bb794ab 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java @@ -567,21 +567,14 @@ public class ExprProcessor implements CodeConstants { case opc_invokeinterface: case opc_invokedynamic: if (instr.opcode != opc_invokedynamic || instr.bytecode_version >= CodeConstants.BYTECODE_JAVA_7) { - LinkConstant invoke_constant = pool.getLinkConstant(instr.getOperand(0)); - int dynamic_invokation_type = -1; + List bootstrap_arguments = null; if (instr.opcode == opc_invokedynamic && bootstrap != null) { - List bootstrap_arguments = bootstrap.getMethodArguments(invoke_constant.index1); - if (bootstrap_arguments.size() > 1) { // INVOKEDYNAMIC is used not only for lambdas - PooledConstant link = bootstrap_arguments.get(1); - if (link instanceof LinkConstant) { - dynamic_invokation_type = ((LinkConstant)link).index1; - } - } + bootstrap_arguments = bootstrap.getMethodArguments(invoke_constant.index1); } - InvocationExprent exprinv = new InvocationExprent(instr.opcode, invoke_constant, stack, dynamic_invokation_type, bytecode_offsets); + InvocationExprent exprinv = new InvocationExprent(instr.opcode, invoke_constant, bootstrap_arguments, stack, bytecode_offsets); if (exprinv.getDescriptor().ret.type == CodeConstants.TYPE_VOID) { exprlist.add(exprinv); } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java index 294a115207d3..3ceb99cafc60 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,13 +15,6 @@ */ package org.jetbrains.java.decompiler.modules.decompiler.exps; -import java.util.ArrayList; -import java.util.BitSet; -import java.util.Collections; -import java.util.List; -import java.util.Map.Entry; -import java.util.Set; - import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.DecompilerContext; @@ -36,6 +29,7 @@ import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPair; import org.jetbrains.java.decompiler.struct.StructClass; import org.jetbrains.java.decompiler.struct.StructMethod; import org.jetbrains.java.decompiler.struct.consts.LinkConstant; +import org.jetbrains.java.decompiler.struct.consts.PooledConstant; import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor; import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.match.MatchEngine; @@ -45,6 +39,9 @@ import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.ListStack; import org.jetbrains.java.decompiler.util.TextUtil; +import java.util.*; +import java.util.Map.Entry; + public class InvocationExprent extends Exprent { public static final int INVOKE_SPECIAL = 1; @@ -69,16 +66,22 @@ public class InvocationExprent extends Exprent { private String invokeDynamicClassSuffix; private int invocationTyp = INVOKE_VIRTUAL; private List lstParameters = new ArrayList(); + private List bootstrapArguments; public InvocationExprent() { super(EXPRENT_INVOCATION); } - public InvocationExprent(int opcode, LinkConstant cn, ListStack stack, int dynamicInvocationType, Set bytecodeOffsets) { + public InvocationExprent(int opcode, + LinkConstant cn, + List bootstrapArguments, + ListStack stack, + Set bytecodeOffsets) { this(); name = cn.elementname; classname = cn.classname; + this.bootstrapArguments = bootstrapArguments; switch (opcode) { case CodeConstants.opc_invokestatic: @@ -115,6 +118,15 @@ public class InvocationExprent extends Exprent { } if (opcode == CodeConstants.opc_invokedynamic) { + int dynamicInvocationType = -1; + if (bootstrapArguments != null) { + if (bootstrapArguments.size() > 1) { // INVOKEDYNAMIC is used not only for lambdas + PooledConstant link = bootstrapArguments.get(1); + if (link instanceof LinkConstant) { + dynamicInvocationType = ((LinkConstant)link).index1; + } + } + } if (dynamicInvocationType == CodeConstants.CONSTANT_MethodHandle_REF_invokeStatic) { isStatic = true; } @@ -154,6 +166,7 @@ public class InvocationExprent extends Exprent { ExprProcessor.copyEntries(lstParameters); addBytecodeOffsets(expr.bytecode); + bootstrapArguments = expr.getBootstrapArguments(); } @Override @@ -492,6 +505,10 @@ public class InvocationExprent extends Exprent { return invokeDynamicClassSuffix; } + public List getBootstrapArguments() { + return bootstrapArguments; + } + // ***************************************************************************** // IMatchable implementation // ***************************************************************************** diff --git a/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java b/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java index 1ab4ea2f3244..b8869b0d64d3 100644 --- a/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java +++ b/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -77,6 +77,8 @@ public class SingleClassesTest { @Test public void testInnerSignature() { doTest("pkg/TestInnerSignature"); } @Test public void testParameterizedTypes() { doTest("pkg/TestParameterizedTypes"); } @Test public void testShadowing() { doTest("pkg/TestShadowing", "pkg/Shadow", "ext/Shadow"); } + @Test public void testStringConcat() { doTest("pkg/TestStringConcat"); } + @Test public void testJava9StringConcat() { doTest("java9/TestJava9StringConcat"); } protected void doTest(String testFile, String... companionFiles) { ConsoleDecompiler decompiler = fixture.getDecompiler(); diff --git a/plugins/java-decompiler/engine/testData/classes/java9/TestJava9StringConcat.class b/plugins/java-decompiler/engine/testData/classes/java9/TestJava9StringConcat.class new file mode 100644 index 0000000000000000000000000000000000000000..721a0ed9499e46d3ea2ea1853198faba1186a168 GIT binary patch literal 871 zcmaJfgc5Pg#-aq6Z`TMGS3OG{IlP?-qCB?{s|q>7>dheUATv`JR28+SLdHuo{bq5=S;%i^| z<_%%4-uO(&cl1aSDqUa6kJHP64EtgbaHe2nWL^-C>fH-*C7OXyXU(1oeRbA8ZQRc# zjF*H~79&OYG`NsM)6UdzdwLoU<%w@w*y?i&@40v@uG`USD9m%)P8mfwgypwdo5+M> z@PnAgGO<|TL=24%uN@rn8oFAKrxQZ?R4EyD0ue=$ zRllW&muSRydneQ=kWnorwo?O5wvx*HL+oEqWCr|e3ZJo(M4}^tpywOecJP#Nc<+8$ zy%Bc*kHbFl{5tJ7$8VEY$+pC&9rnb&@a!k(2M0W6w#A#Iea0>p*jnfwa!dwF$JH5! z_t@r!WN?i(Gq7N{XN?UB 5 +24 <-> 9 diff --git a/plugins/java-decompiler/engine/testData/results/TestStringConcat.dec b/plugins/java-decompiler/engine/testData/results/TestStringConcat.dec new file mode 100644 index 000000000000..b3fc99579d32 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/results/TestStringConcat.dec @@ -0,0 +1,31 @@ +package pkg; + +public class TestStringConcat { + public String test1(String var1, int var2) { + return var1 + var2;// 20 + } + + public String test2(String var1, int var2, Object var3) { + return "(" + var1 + "-" + var2 + "---" + var3 + ")";// 24 + } +} + +class 'pkg/TestStringConcat' { + method 'test1 (Ljava/lang/String;I)Ljava/lang/String;' { + f 4 + 12 4 + } + + method 'test2 (Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String;' { + 7 8 + 10 8 + 19 8 + 22 8 + 27 8 + 2a 8 + } +} + +Lines mapping: +20 <-> 5 +24 <-> 9 diff --git a/plugins/java-decompiler/engine/testData/src/java9/TestJava9StringConcat.java b/plugins/java-decompiler/engine/testData/src/java9/TestJava9StringConcat.java new file mode 100644 index 000000000000..9e1959649e53 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/src/java9/TestJava9StringConcat.java @@ -0,0 +1,26 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package java9; + +public class TestJava9StringConcat { + public String test1(String prefix, int a) { + return prefix + a; + } + + public String test2(String var, int b, Object c) { + return "(" + var + "-" + b + "---" + c + ")"; + } +} \ No newline at end of file diff --git a/plugins/java-decompiler/engine/testData/src/pkg/TestStringConcat.class b/plugins/java-decompiler/engine/testData/src/pkg/TestStringConcat.class new file mode 100644 index 0000000000000000000000000000000000000000..029207376cef59555729fc47605dda16cd3b41b5 GIT binary patch literal 740 zcmZ`%O;5r=5PeI5){24!1Qk^LqChIqcrh3cl9-qfJwQx67HCKjTT+X^OD`qS#2?^~ zGR{g33bo0;-I?us^JcOipRex#PEeMygsg})86jjjtaI4lkdu&?uqk1SN81t#B6dXV zGDOcz%XH5f1hsU_5U$%@gCX89E#rFh&^DZw-X2gU;u??c5kpaJ^z|pbI?%0Nwdp#h z)vH~V=5s#dnBg>t@r!WN?i(Gq7N{XN?UB Date: Tue, 1 Mar 2016 18:21:23 +0300 Subject: [PATCH 20/23] inspection tool window: update nodes when fix action is invoked (IDEA-152226) --- .../intellij/codeInspection/ex/QuickFixAction.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/QuickFixAction.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/QuickFixAction.java index abd82c1a8789..1b75f63bcb83 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/QuickFixAction.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/QuickFixAction.java @@ -46,6 +46,9 @@ import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import javax.swing.*; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; import java.util.*; /** @@ -170,6 +173,15 @@ public class QuickFixAction extends AnAction { }, templatePresentationText, null); refreshViews(project, ignoredElements, myToolWrapper); + final InspectionTree tree = context.getView().getTree(); + final TreePath[] selected = tree.getSelectionPaths(); + if (selected != null) { + for (TreePath path : selected) { + path.getLastPathComponent(); + ((DefaultTreeModel) tree.getModel()).reload((TreeNode)path.getLastPathComponent()); + } + } + tree.restoreExpansionAndSelection(); } finally { //to make offline view lazy if (initial) refManager.inspectionReadActionStarted(); From b632a7fb2754d64741e998863fef5d76fcdb2cc8 Mon Sep 17 00:00:00 2001 From: Sergey Simonchik Date: Tue, 1 Mar 2016 18:24:48 +0300 Subject: [PATCH 21/23] quick doc: scale font size for HiDPI displays --- .../codeInsight/documentation/DocumentationComponent.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java index 8139591df006..ca9c21e1c952 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java @@ -59,6 +59,7 @@ import com.intellij.util.Consumer; import com.intellij.util.containers.HashMap; import com.intellij.util.ui.GraphicsUtil; import com.intellij.util.ui.JBDimension; +import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -626,7 +627,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr EditorColorsManager colorsManager = EditorColorsManager.getInstance(); EditorColorsScheme scheme = colorsManager.getGlobalScheme(); - StyleConstants.setFontSize(myFontSizeStyle, scheme.getQuickDocFontSize().getSize()); + StyleConstants.setFontSize(myFontSizeStyle, JBUI.scale(scheme.getQuickDocFontSize().getSize())); if (Registry.is("documentation.component.editor.font")) { StyleConstants.setFontFamily(myFontSizeStyle, scheme.getEditorFontName()); } From a0088dc7115a2ca77d42c22e9d6bc68d85aa57e2 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Tue, 1 Mar 2016 18:25:24 +0300 Subject: [PATCH 22/23] IDEA-152295 StringUtil.pluralize() is incorrect --- .../util/src/com/intellij/openapi/util/text/StringUtil.java | 3 ++- .../util/testSrc/com/intellij/util/text/StringUtilTest.java | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index 449323a395a9..456a0ac0d5c0 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -852,7 +852,8 @@ public class StringUtil extends StringUtilRt { return suggestion.substring(0, len - 2) + "en"; } - if (endsWithIgnoreCase(suggestion, "s") || endsWithIgnoreCase(suggestion, "x") || endsWithIgnoreCase(suggestion, "ch")) { + if (endsWithIgnoreCase(suggestion, "s") || endsWithIgnoreCase(suggestion, "x") || + endsWithIgnoreCase(suggestion, "ch") || endsWithIgnoreCase(suggestion, "sh")) { return suggestion + "es"; } diff --git a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java index 5282ab84f5f7..f8136aebdde0 100644 --- a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java +++ b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java @@ -110,6 +110,7 @@ public class StringUtilTest { assertEquals("fixes", StringUtil.pluralize("fix")); assertEquals("men", StringUtil.pluralize("man")); assertEquals("media", StringUtil.pluralize("medium")); + assertEquals("stashes", StringUtil.pluralize("stash")); } @Test From c7a5a68eaa0717b92aab53a05f64e1e4925445d9 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 1 Mar 2016 16:26:34 +0100 Subject: [PATCH 23/23] to avoid API breakage, restore PathUIUtils class as deprecated --- .../LibrarySourceRootDetectorUtil.java | 2 +- .../roots/ui/configuration/PathUIUtils.java | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/PathUIUtils.java diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/LibrarySourceRootDetectorUtil.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/LibrarySourceRootDetectorUtil.java index 6c310c35dc71..e7b9dc016648 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/LibrarySourceRootDetectorUtil.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/LibrarySourceRootDetectorUtil.java @@ -37,7 +37,7 @@ import java.util.List; public class LibrarySourceRootDetectorUtil { public static ExtensionPointName JAVA_SOURCE_ROOT_DETECTOR = ExtensionPointName.create("com.intellij.library.javaSourceRootDetector"); - private LibrarySourceRootDetectorUtil() { + protected LibrarySourceRootDetectorUtil() { } /** diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/PathUIUtils.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/PathUIUtils.java new file mode 100644 index 000000000000..27d947963e5b --- /dev/null +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/PathUIUtils.java @@ -0,0 +1,26 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.roots.ui.configuration; + +import com.intellij.openapi.roots.libraries.ui.RootDetector; + +/** + * @deprecated please use {@link LibrarySourceRootDetectorUtil} directly + */ +public class PathUIUtils extends LibrarySourceRootDetectorUtil { + public static final RootDetector JAVA_SOURCE_ROOT_DETECTOR = new LibraryJavaSourceRootDetector(); + +}