diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java index 9ceffac57eb4..9648285288a1 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java @@ -93,6 +93,7 @@ import io.netty.handler.codec.protobuf.ProtobufDecoder; import io.netty.handler.codec.protobuf.ProtobufEncoder; import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder; import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; +import io.netty.util.internal.ThreadLocalRandom; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.ide.PooledThreadExecutor; @@ -999,6 +1000,9 @@ public class BuildManager implements ApplicationComponent{ cmdLine.addParameter("-Didea.case.sensitive.fs=" + isFSCaseSensitive); } + // this will make netty initialization faster on some systems + cmdLine.addParameter("-Dio.netty.initialSeedUniquifier=" + ThreadLocalRandom.getInitialSeedUniquifier()); + boolean isProfilingMode = false; final String additionalOptions = config.COMPILER_PROCESS_ADDITIONAL_VM_OPTIONS; if (!StringUtil.isEmpty(additionalOptions)) { diff --git a/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java b/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java index 65c6777bcbbb..e4103ce1a9c9 100644 --- a/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java @@ -106,7 +106,7 @@ public class CodeInsightUtil { if (parent == null) return PsiElement.EMPTY_ARRAY; while (true) { if (parent instanceof PsiStatement) { - if (!(element1 instanceof PsiComment || element2 instanceof PsiComment)) { + if (!(element1 instanceof PsiComment)) { parent = parent.getParent(); } break; diff --git a/platform/icons/src/ide/shadow/bottom-left@2x.png b/platform/icons/src/ide/shadow/bottom-left@2x.png new file mode 100644 index 000000000000..10e5d1c9c5f6 Binary files /dev/null and b/platform/icons/src/ide/shadow/bottom-left@2x.png differ diff --git a/platform/icons/src/ide/shadow/bottom-right@2x.png b/platform/icons/src/ide/shadow/bottom-right@2x.png new file mode 100644 index 000000000000..771dfef1db73 Binary files /dev/null and b/platform/icons/src/ide/shadow/bottom-right@2x.png differ diff --git a/platform/icons/src/ide/shadow/bottom@2x.png b/platform/icons/src/ide/shadow/bottom@2x.png new file mode 100644 index 000000000000..ad69deefa9b6 Binary files /dev/null and b/platform/icons/src/ide/shadow/bottom@2x.png differ diff --git a/platform/icons/src/ide/shadow/left@2x.png b/platform/icons/src/ide/shadow/left@2x.png new file mode 100644 index 000000000000..78c558d74d75 Binary files /dev/null and b/platform/icons/src/ide/shadow/left@2x.png differ diff --git a/platform/icons/src/ide/shadow/popup/bottom-left@2x.png b/platform/icons/src/ide/shadow/popup/bottom-left@2x.png new file mode 100644 index 000000000000..17b7f4d2682e Binary files /dev/null and b/platform/icons/src/ide/shadow/popup/bottom-left@2x.png differ diff --git a/platform/icons/src/ide/shadow/popup/bottom-right@2x.png b/platform/icons/src/ide/shadow/popup/bottom-right@2x.png new file mode 100644 index 000000000000..3404aa0dd95f Binary files /dev/null and b/platform/icons/src/ide/shadow/popup/bottom-right@2x.png differ diff --git a/platform/icons/src/ide/shadow/popup/bottom@2x.png b/platform/icons/src/ide/shadow/popup/bottom@2x.png new file mode 100644 index 000000000000..cb4fcb9fbb95 Binary files /dev/null and b/platform/icons/src/ide/shadow/popup/bottom@2x.png differ diff --git a/platform/icons/src/ide/shadow/popup/left@2x.png b/platform/icons/src/ide/shadow/popup/left@2x.png new file mode 100644 index 000000000000..86b5ae995f3e Binary files /dev/null and b/platform/icons/src/ide/shadow/popup/left@2x.png differ diff --git a/platform/icons/src/ide/shadow/popup/right@2x.png b/platform/icons/src/ide/shadow/popup/right@2x.png new file mode 100644 index 000000000000..6c54fe7bfd24 Binary files /dev/null and b/platform/icons/src/ide/shadow/popup/right@2x.png differ diff --git a/platform/icons/src/ide/shadow/popup/top-left@2x.png b/platform/icons/src/ide/shadow/popup/top-left@2x.png new file mode 100644 index 000000000000..3a6ca6530854 Binary files /dev/null and b/platform/icons/src/ide/shadow/popup/top-left@2x.png differ diff --git a/platform/icons/src/ide/shadow/popup/top-right@2x.png b/platform/icons/src/ide/shadow/popup/top-right@2x.png new file mode 100644 index 000000000000..567bd08fbc83 Binary files /dev/null and b/platform/icons/src/ide/shadow/popup/top-right@2x.png differ diff --git a/platform/icons/src/ide/shadow/popup/top@2x.png b/platform/icons/src/ide/shadow/popup/top@2x.png new file mode 100644 index 000000000000..495941809e23 Binary files /dev/null and b/platform/icons/src/ide/shadow/popup/top@2x.png differ diff --git a/platform/icons/src/ide/shadow/right@2x.png b/platform/icons/src/ide/shadow/right@2x.png new file mode 100644 index 000000000000..d2afef8fd36d Binary files /dev/null and b/platform/icons/src/ide/shadow/right@2x.png differ diff --git a/platform/icons/src/ide/shadow/top-left@2x.png b/platform/icons/src/ide/shadow/top-left@2x.png new file mode 100644 index 000000000000..5d01020b6fc8 Binary files /dev/null and b/platform/icons/src/ide/shadow/top-left@2x.png differ diff --git a/platform/icons/src/ide/shadow/top-right@2x.png b/platform/icons/src/ide/shadow/top-right@2x.png new file mode 100644 index 000000000000..d63848c3fb50 Binary files /dev/null and b/platform/icons/src/ide/shadow/top-right@2x.png differ diff --git a/platform/icons/src/ide/shadow/top@2x.png b/platform/icons/src/ide/shadow/top@2x.png new file mode 100644 index 000000000000..a893e2458eec Binary files /dev/null and b/platform/icons/src/ide/shadow/top@2x.png differ diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.form b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.form index b6e07f4c8a5b..3c6a16512e86 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.form +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.form @@ -107,7 +107,7 @@ - + diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java index 6dc2971b800c..cd0a9c0890f2 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java @@ -51,6 +51,7 @@ public class LayoutCodeDialog extends DialogWrapper { private JPanel myActionsPanel; private JPanel myScopePanel; + private JLabel myOptionalLabel; private LayoutCodeOptions myRunOptions; @@ -127,6 +128,8 @@ public class LayoutCodeDialog extends DialogWrapper { if (canRearrangeCode) { myRearrangeCodeCb.setSelected(myLastRunOptions.isRearrangeCode(myFile.getLanguage())); } + + myOptionalLabel.setVisible(canOptimizeImports || canRearrangeCode); } @Nullable diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/IntelliJLaf.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/IntelliJLaf.java index 2df9bf7f6414..e1e77fb8354f 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/IntelliJLaf.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/IntelliJLaf.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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,11 +15,8 @@ */ package com.intellij.ide.ui.laf; -import com.intellij.ide.ui.LafManager; import com.intellij.ide.ui.laf.darcula.DarculaLaf; -import com.intellij.openapi.util.SystemInfo; -import javax.swing.*; import javax.swing.plaf.metal.DefaultMetalTheme; /** @@ -36,19 +33,6 @@ public class IntelliJLaf extends DarculaLaf { return "intellijlaf"; } - @Override - public UIDefaults getDefaults() { - UIDefaults defaults = super.getDefaults(); - if (SystemInfo.isLinux) { - try { - LafManagerImpl.initFontDefaults(defaults, "Dialog", 12); - } - catch (Exception ignore) { - } - } - return defaults; - } - @Override protected DefaultMetalTheme createMetalTheme() { return new IdeaBlueMetalTheme(); diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java index 779e326d2802..0a2ce8d93e67 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java @@ -560,6 +560,7 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo List myIntKeys = Arrays.asList("Tree.leftChildIndent", "Tree.rightChildIndent"); + List patched = new ArrayList(); for (Map.Entry entry : defaults.entrySet()) { Object value = entry.getValue(); String key = entry.getKey().toString(); @@ -569,10 +570,16 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo entry.setValue(JBUI.insets(((InsetsUIResource)value)).asUIResource()); } else if (value instanceof Integer) { if (key.endsWith(".maxGutterIconWidth") || myIntKeys.contains(key)) { - entry.setValue(Integer.valueOf(JBUI.scale((Integer)value))); + if (!"true".equals(defaults.get(key +".hidpi.patched"))) { + entry.setValue(Integer.valueOf(JBUI.scale((Integer)value))); + patched.add(key); + } } } } + for (String key : patched) { + defaults.put(key + ".hidpi.patched", "true"); + } } public static void updateToolWindows() { diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java index 156c39657609..8e9ca5a93e52 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java @@ -42,10 +42,8 @@ import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.URL; -import java.util.Arrays; +import java.util.*; import java.util.List; -import java.util.Locale; -import java.util.Properties; /** * @author Konstantin Bulenkov @@ -82,7 +80,7 @@ public class DarculaLaf extends BasicLookAndFeel { @SuppressWarnings("UnusedParameters") private static void log(Exception e) { // everything is gonna be alright -// e.printStackTrace(); + e.printStackTrace(); } @Override @@ -91,6 +89,7 @@ public class DarculaLaf extends BasicLookAndFeel { final Method superMethod = BasicLookAndFeel.class.getDeclaredMethod("getDefaults"); superMethod.setAccessible(true); final UIDefaults metalDefaults = (UIDefaults)superMethod.invoke(new MetalLookAndFeel()); + final UIDefaults defaults = (UIDefaults)superMethod.invoke(base); if (SystemInfo.isLinux) { if (!Registry.is("darcula.use.native.fonts.on.linux")) { @@ -124,6 +123,9 @@ public class DarculaLaf extends BasicLookAndFeel { if (SystemInfo.isWindows) { //JFrame.setDefaultLookAndFeelDecorated(true); } + if (SystemInfo.isLinux && JBUI.isHiDPI()) { + applySystemFonts(defaults); + } defaults.put("EditorPane.font", defaults.getFont("TextField.font")); return defaults; } @@ -133,6 +135,23 @@ public class DarculaLaf extends BasicLookAndFeel { return super.getDefaults(); } + private static void applySystemFonts(UIDefaults defaults) { + try { + String fqn = UIManager.getSystemLookAndFeelClassName(); + Object systemLookAndFeel = Class.forName(fqn).newInstance(); + final Method superMethod = BasicLookAndFeel.class.getDeclaredMethod("getDefaults"); + superMethod.setAccessible(true); + final UIDefaults systemDefaults = (UIDefaults)superMethod.invoke(systemLookAndFeel); + for (Map.Entry entry : systemDefaults.entrySet()) { + if (entry.getValue() instanceof Font) { + defaults.put(entry.getKey(), entry.getValue()); + } + } + } catch (Exception e) { + log(e); + } + } + protected DefaultMetalTheme createMetalTheme() { return new DarculaMetalTheme(); } diff --git a/platform/platform-impl/src/com/intellij/ui/Splash.java b/platform/platform-impl/src/com/intellij/ui/Splash.java index 0bee1412af15..fcab3aa223ab 100644 --- a/platform/platform-impl/src/com/intellij/ui/Splash.java +++ b/platform/platform-impl/src/com/intellij/ui/Splash.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -47,7 +47,7 @@ public class Splash extends JDialog implements StartupProgress { @Nullable public static Rectangle BOUNDS; private final Icon myImage; - private int myProgressHeight = 2; + private int myProgressHeight = JBUI.scale(2); private Color myProgressColor = null; private int myProgressY; private float myProgress; @@ -102,7 +102,7 @@ public class Splash extends JDialog implements StartupProgress { this(info.getSplashImageUrl(), info.getSplashTextColor()); if (info instanceof ApplicationInfoImpl) { final ApplicationInfoImpl appInfo = (ApplicationInfoImpl)info; - myProgressHeight = 2; + myProgressHeight = JBUI.scale(2); myProgressColor = appInfo.getProgressColor(); myProgressY = appInfo.getProgressY(); myProgressTail = appInfo.getProgressTailIcon(); @@ -143,8 +143,8 @@ public class Splash extends JDialog implements StartupProgress { g.setColor(color); g.fillRect(1, getProgressY(), width, getProgressHeight()); if (myProgressTail != null) { - myProgressTail.paintIcon(this, g, width - (myProgressTail.getIconWidth()/2), - getProgressY() - (myProgressTail.getIconHeight() - getProgressHeight())/2); + myProgressTail.paintIcon(this, g, width - (myProgressTail.getIconWidth() / JBUI.scale(1) / 2 * JBUI.scale(1)), + getProgressY() - (myProgressTail.getIconHeight() - getProgressHeight()) / JBUI.scale(1) / 2 * JBUI.scale(1)); //I'll buy you a beer if you understand this line without playing with it } myProgressLastPosition = progressWidth; } diff --git a/platform/util/src/com/intellij/util/ImageLoader.java b/platform/util/src/com/intellij/util/ImageLoader.java index 1fcc08ea333b..b8ac405c97f3 100644 --- a/platform/util/src/com/intellij/util/ImageLoader.java +++ b/platform/util/src/com/intellij/util/ImageLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -30,6 +30,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; @@ -63,7 +65,14 @@ public class ImageLoader implements Serializable { public static Image loadFromUrl(@NotNull URL url) { for (Pair each : getFileNames(url.toString())) { try { - return loadFromStream(URLUtil.openStream(new URL(each.first)), each.second); + Image image = loadFromStream(URLUtil.openStream(new URL(each.first)), each.second); + + //we can't check all 3rd party plugins and convince the authors to add @2x icons. + // isHiDPI() != isRetina() => we should scale images manually + if (image != null && JBUI.isHiDPI() && !each.first.contains("@2x")) { + image = upscale(image); + } + return image; } catch (IOException ignore) { } @@ -71,6 +80,19 @@ public class ImageLoader implements Serializable { return null; } + @NotNull + private static Image upscale(Image image) { + float scale = JBUI.scale(1f); + int width = (int)(scale * image.getWidth(null)); + int height = (int)(scale * image.getHeight(null)); + @SuppressWarnings("UndesirableClassUsage") + BufferedImage tmp = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = tmp.createGraphics(); + g.drawImage(image, AffineTransform.getScaleInstance(scale, scale), null); + image = tmp; + return image; + } + @Nullable public static Image loadFromUrl(URL url, boolean dark, boolean retina) { for (Pair each : getFileNames(url.toString(), dark, retina || JBUI.isHiDPI())) { diff --git a/platform/util/src/com/intellij/util/SystemProperties.java b/platform/util/src/com/intellij/util/SystemProperties.java index 7929dd1ff629..14b6999cb868 100644 --- a/platform/util/src/com/intellij/util/SystemProperties.java +++ b/platform/util/src/com/intellij/util/SystemProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -135,4 +135,12 @@ public class SystemProperties { public static String getJavaVendor() { return System.getProperty("java.vendor"); } + + public static boolean is(String key) { + return getBooleanProperty(key, false); + } + + public static boolean has(String key) { + return System.getProperty(key) != null; + } } diff --git a/platform/util/src/com/intellij/util/ui/JBUI.java b/platform/util/src/com/intellij/util/ui/JBUI.java index 0c80b543d838..70f4539f958a 100644 --- a/platform/util/src/com/intellij/util/ui/JBUI.java +++ b/platform/util/src/com/intellij/util/ui/JBUI.java @@ -17,6 +17,7 @@ package com.intellij.util.ui; import com.intellij.openapi.util.SystemInfo; import com.intellij.ui.border.CustomLineBorder; +import com.intellij.util.SystemProperties; import javax.swing.*; import javax.swing.border.Border; @@ -26,7 +27,27 @@ import java.awt.*; * @author Konstantin Bulenkov */ public class JBUI { - private static boolean IS_HIDPI = !SystemInfo.isMac && ("true".equals(System.getProperty("hidpi")) || "true".equals(System.getProperty("is.hidpi"))); + private static boolean IS_HIDPI = calculateHiDPI(); + + private static boolean calculateHiDPI() { + if (SystemInfo.isMac) { + return false; + } + + if (SystemProperties.is("hidpi")) { + return true; + } + + if (SystemProperties.has("hidpi") && !SystemProperties.is("hidpi")) { + return false; + } + + if (SystemInfo.isWindows && getSystemDPI() > 144) { + return true; + } + + return false; + } private static int getSystemDPI() { try { diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java index 28669193d19a..9961a7103f18 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java @@ -15,7 +15,6 @@ */ package com.siyeh.ig.style; -import com.intellij.codeInsight.javadoc.JavaDocUtil; import com.intellij.codeInspection.CleanupLocalInspectionTool; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.diagnostic.Logger; @@ -26,6 +25,7 @@ import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.JavaCodeStyleSettings; +import com.intellij.psi.impl.source.codeStyle.ImportHelper; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; @@ -206,11 +206,6 @@ public class UnnecessaryFullyQualifiedNameInspection extends BaseInspection impl if (element != null) { return; } - final CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(reference.getProject()); - PsiDocComment containingComment = PsiTreeUtil.getParentOfType(reference, PsiDocComment.class); - if (containingComment != null && acceptFullyQualifiedNamesInJavadoc(containingComment, styleSettings)) { - return; - } final PsiFile containingFile = reference.getContainingFile(); if (!(containingFile instanceof PsiJavaFile)) { return; @@ -219,6 +214,11 @@ public class UnnecessaryFullyQualifiedNameInspection extends BaseInspection impl if (!(target instanceof PsiClass)) { return; } + final CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(reference.getProject()); + PsiDocComment containingComment = PsiTreeUtil.getParentOfType(reference, PsiDocComment.class); + if (containingComment != null && acceptFqnInJavadoc((PsiJavaFile)containingFile, reference.getQualifiedName(), styleSettings)) { + return; + } final PsiJavaCodeReferenceElement qualifierReference = (PsiJavaCodeReferenceElement)qualifier; final PsiElement qualifierTarget = qualifierReference.resolve(); if (!(qualifierTarget instanceof PsiPackage)) { @@ -262,11 +262,14 @@ public class UnnecessaryFullyQualifiedNameInspection extends BaseInspection impl } } - public static boolean acceptFullyQualifiedNamesInJavadoc(PsiDocComment comment, CodeStyleSettings styleSettings) { - if (JavaDocUtil.isInsidePackageInfo(comment)) { + private static boolean acceptFqnInJavadoc(PsiJavaFile javaFile, String fullyQualifiedName, CodeStyleSettings styleSettings) { + if ("package-info.java".equals(javaFile.getName())) { return true; } JavaCodeStyleSettings javaSettings = styleSettings.getCustomSettings(JavaCodeStyleSettings.class); + if (javaSettings.CLASS_NAMES_IN_JAVADOC == JavaCodeStyleSettings.FULLY_QUALIFY_NAMES_IF_NOT_IMPORTED) { + return !ImportHelper.isAlreadyImported(javaFile, fullyQualifiedName); + } return javaSettings.useFqNamesInJavadocAlways(); } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/DoubleQualify.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/DoubleQualify.java new file mode 100644 index 000000000000..de1e31544974 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/DoubleQualify.java @@ -0,0 +1,7 @@ +import java.util.HashMap; + +/** + * {@link java.util.HashMap} + */ +public class DoubleQualify { +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/Single.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/Single.java new file mode 100644 index 000000000000..193c25f043c5 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/Single.java @@ -0,0 +1,5 @@ +/** + * {@link java.util.HashMap} + */ +public class Single { +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/expected.xml new file mode 100644 index 000000000000..05706352d657 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/expected.xml @@ -0,0 +1,11 @@ + + + + + DoubleQualify.java + 4 + Unnecessary fully qualified name + Fully qualified name <code>java.util.HashMap</code> is unnecessary, and can be replaced with an import #loc + + + \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspectionTest.java index 8dc9ea7b861c..1856fc662a46 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspectionTest.java @@ -10,7 +10,7 @@ public class UnnecessaryFullyQualifiedNameInspectionTest extends IGInspectionTes private static final String BASE_DIR = "com/siyeh/igtest/style/"; public void testFqnInJavadoc_Unnecessary_WhenFullyQualifyIfNotImported() throws Exception { - doTestWithFqnInJavadocSetting(BASE_DIR + "unnecessary_fully_qualified_name/", JavaCodeStyleSettings.FULLY_QUALIFY_NAMES_IF_NOT_IMPORTED); + doTestWithFqnInJavadocSetting(BASE_DIR + "unnecessary_fqn_javadoc_fully_qualify_if_not_imported", JavaCodeStyleSettings.FULLY_QUALIFY_NAMES_IF_NOT_IMPORTED); } public void testFqnInJavadoc_Unnecessary_WhenShortNamesAlways() { diff --git a/plugins/java-i18n/src/META-INF/plugin.xml b/plugins/java-i18n/src/META-INF/plugin.xml index c3e2c5aab225..9d4fc9a8f356 100644 --- a/plugins/java-i18n/src/META-INF/plugin.xml +++ b/plugins/java-i18n/src/META-INF/plugin.xml @@ -54,6 +54,12 @@ enabledByDefault="true" level="WARNING" implementationClass="com.intellij.codeInspection.capitalization.TitleCapitalizationInspection"/> + com.intellij.codeInspection.capitalization.AnnotateCapitalizationIntention diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/SuspiciousLocalesLanguagesInspection.java b/plugins/java-i18n/src/com/intellij/codeInspection/SuspiciousLocalesLanguagesInspection.java new file mode 100644 index 000000000000..1dc726b8a2ee --- /dev/null +++ b/plugins/java-i18n/src/com/intellij/codeInspection/SuspiciousLocalesLanguagesInspection.java @@ -0,0 +1,237 @@ +/* + * Copyright 2000-2015 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.codeInspection; + +import com.intellij.codeInspection.ex.BaseLocalInspectionTool; +import com.intellij.lang.properties.*; +import com.intellij.lang.properties.ResourceBundle; +import com.intellij.lang.properties.customizeActions.DissociateResourceBundleAction; +import com.intellij.lang.properties.psi.PropertiesFile; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.InputValidator; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.InvalidDataException; +import com.intellij.openapi.util.WriteExternalException; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiFile; +import com.intellij.reference.SoftLazyValue; +import com.intellij.ui.AnActionButton; +import com.intellij.ui.AnActionButtonRunnable; +import com.intellij.ui.ToolbarDecorator; +import com.intellij.ui.components.JBList; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.HashSet; +import org.jdom.Element; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; + +import javax.swing.*; +import java.awt.*; +import java.util.*; +import java.util.List; + +/** + * @author Dmitry Batkovich + */ +public class SuspiciousLocalesLanguagesInspection extends BaseLocalInspectionTool { + private static final String ADDITIONAL_LANGUAGES_ATTR_NAME = "additionalLanguages"; + private final static SoftLazyValue> JAVA_LOCALES = new SoftLazyValue>() { + @NotNull + @Override + protected Set compute() { + final Set result = new HashSet(); + for (Locale locale : Locale.getAvailableLocales()) { + result.add(locale.getLanguage()); + } + return result; + } + }; + + private final List myAdditionalLanguages = new ArrayList(); + + @Nls + @NotNull + @Override + public String getDisplayName() { + return "Suspicious resource bundle locale languages"; + } + + @TestOnly + public void setAdditionalLanguages(List additionalLanguages) { + myAdditionalLanguages.clear(); + myAdditionalLanguages.addAll(additionalLanguages); + } + + @Override + public void readSettings(@NotNull Element node) throws InvalidDataException { + final String rawLanguages = node.getAttributeValue(ADDITIONAL_LANGUAGES_ATTR_NAME); + if (rawLanguages != null) { + myAdditionalLanguages.clear(); + myAdditionalLanguages.addAll(StringUtil.split(rawLanguages, ",")); + } + } + + @Override + public void writeSettings(@NotNull Element node) throws WriteExternalException { + if (!myAdditionalLanguages.isEmpty()) { + final ArrayList uniqueLanguages = ContainerUtil.newArrayList(ContainerUtil.newHashSet(myAdditionalLanguages)); + Collections.sort(uniqueLanguages); + final String locales = StringUtil.join(uniqueLanguages, ","); + node.setAttribute(ADDITIONAL_LANGUAGES_ATTR_NAME, locales); + } + } + + @Nullable + @Override + public JComponent createOptionsPanel() { + return new MyOptions().getComponent(); + } + + @Nullable + @Override + public ProblemDescriptor[] checkFile(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) { + final PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile(file); + if (propertiesFile == null) { + return null; + } + final ResourceBundle resourceBundle = propertiesFile.getResourceBundle(); + final List files = resourceBundle.getPropertiesFiles(); + if (!(resourceBundle instanceof ResourceBundleImpl) || files.size() < 2) { + return null; + } + List bundleLocales = ContainerUtil.mapNotNull(files, new Function() { + @Override + public Locale fun(PropertiesFile propertiesFile) { + final Locale locale = propertiesFile.getLocale(); + return locale == ResourceBundleManager.DEFAULT_LOCALE ? null : locale; + } + }); + bundleLocales = ContainerUtil.filter(bundleLocales, new Condition() { + @Override + public boolean value(Locale locale) { + return !JAVA_LOCALES.getValue().contains(locale.getLanguage()) && !myAdditionalLanguages.contains(locale.getLanguage()); + } + }); + if (bundleLocales.isEmpty()) { + return null; + } + final ProblemDescriptor descriptor = manager.createProblemDescriptor(file, + PropertiesBundle.message( + "resource.bundle.contains.locales.with.suspicious.locale.languages.desciptor"), + new DissociateResourceBundleQuickFix(resourceBundle), + ProblemHighlightType.WEAK_WARNING, + true); + return new ProblemDescriptor[] {descriptor}; + } + + private static class DissociateResourceBundleQuickFix implements LocalQuickFix { + private final ResourceBundle myResourceBundle; + + private DissociateResourceBundleQuickFix(ResourceBundle bundle) { + myResourceBundle = bundle; + } + + @Nls + @NotNull + @Override + public String getName() { + return getFamilyName(); + } + + @NotNull + @Override + public String getFamilyName() { + return PropertiesBundle.message("dissociate.resource.bundle.quick.fix.name"); + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + DissociateResourceBundleAction.dissociate(Collections.singleton(myResourceBundle), project); + } + } + + private class MyOptions { + private JBList myAdditionalLocalesList; + + public MyOptions() { + myAdditionalLocalesList = new JBList(new MyListModel()); + myAdditionalLocalesList.setCellRenderer(new DefaultListCellRenderer()); + } + + public JPanel getComponent() { + final JPanel panel = new JPanel(new BorderLayout()); + panel.add(new JLabel(PropertiesBundle.message("dissociate.resource.bundle.quick.fix.options.label")), BorderLayout.NORTH); + panel.add( + ToolbarDecorator.createDecorator(myAdditionalLocalesList) + .setAddAction(new AnActionButtonRunnable() { + @Override + public void run(AnActionButton button) { + Messages.showInputDialog(panel, PropertiesBundle.message("dissociate.resource.bundle.quick.fix.options.input.text"), + PropertiesBundle.message("dissociate.resource.bundle.quick.fix.options.input.title"), null, "", new InputValidator() { + @Override + public boolean checkInput(String inputString) { + return 1 < inputString.length() && inputString.length() < 9 && !myAdditionalLanguages.contains(inputString); + } + + @Override + public boolean canClose(String inputString) { + if (inputString != null) { + myAdditionalLanguages.add(inputString); + ((MyListModel)myAdditionalLocalesList.getModel()).fireContentsChanged(); + } + return true; + } + }); + } + }) + .setRemoveAction(new AnActionButtonRunnable() { + @Override + public void run(AnActionButton button) { + final int index = myAdditionalLocalesList.getSelectedIndex(); + if (index > -1 && index < myAdditionalLanguages.size()) { + myAdditionalLanguages.remove(index); + ((MyListModel)myAdditionalLocalesList.getModel()).fireContentsChanged(); + } + } + }) + .setPreferredSize(new Dimension(-1, 100)) + .disableUpDownActions() + .createPanel(), + BorderLayout.CENTER); + return panel; + } + + private class MyListModel extends AbstractListModel { + @Override + public int getSize() { + return myAdditionalLanguages.size(); + } + + @Override + public Object getElementAt(int index) { + return myAdditionalLanguages.get(index); + } + + public void fireContentsChanged() { + fireContentsChanged(myAdditionalLanguages, -1, -1); + } + } + } +} diff --git a/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple1/p.properties b/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple1/p.properties new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple1/p_en.properties b/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple1/p_en.properties new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple2/p.properties b/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple2/p.properties new file mode 100644 index 000000000000..cb17b36e6685 --- /dev/null +++ b/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple2/p.properties @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple2/p_asd.properties b/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple2/p_asd.properties new file mode 100644 index 000000000000..cb17b36e6685 --- /dev/null +++ b/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple2/p_asd.properties @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/plugins/java-i18n/testData/inspections/suspiciousLanguages/withAdditionalLocales/p.properties b/plugins/java-i18n/testData/inspections/suspiciousLanguages/withAdditionalLocales/p.properties new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/plugins/java-i18n/testData/inspections/suspiciousLanguages/withAdditionalLocales/p_asd.properties b/plugins/java-i18n/testData/inspections/suspiciousLanguages/withAdditionalLocales/p_asd.properties new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/plugins/java-i18n/testSrc/com/intellij/codeInspection/SuspiciousLanguagesInspectionTest.java b/plugins/java-i18n/testSrc/com/intellij/codeInspection/SuspiciousLanguagesInspectionTest.java new file mode 100644 index 000000000000..891b8fcffe34 --- /dev/null +++ b/plugins/java-i18n/testSrc/com/intellij/codeInspection/SuspiciousLanguagesInspectionTest.java @@ -0,0 +1,55 @@ +/* + * Copyright 2000-2015 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.codeInspection; + +import com.intellij.openapi.application.PluginPathManager; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import com.intellij.util.containers.ContainerUtil; + +import java.io.File; + +/** + * @author Dmitry Batkovich + */ +public class SuspiciousLanguagesInspectionTest extends LightCodeInsightFixtureTestCase { + @Override + protected String getBasePath() { + return PluginPathManager.getPluginHomePathRelative("java-i18n") + "/testData/inspections/suspiciousLanguages"; + } + + public void testSimple1() { + doTest("p.properties", "p_en.properties"); + } + + public void testSimple2() { + doTest("p.properties", "p_asd.properties"); + } + + public void testWithAdditionalLocales() { + doTest("p.properties", "p_asd.properties", "asd"); + } + + private void doTest(final String file1, final String file2, final String... additionalLocales) { + myFixture.configureByFile(getTestName(true) + "/" + file1); + myFixture.configureByFile(getTestName(true) + "/" + file2); + final SuspiciousLocalesLanguagesInspection inspection = new SuspiciousLocalesLanguagesInspection(); + if (additionalLocales.length != 0) { + inspection.setAdditionalLanguages(ContainerUtil.newArrayList(additionalLocales)); + } + myFixture.enableInspections(inspection); + myFixture.checkHighlighting(); + } +} diff --git a/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties b/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties index aefabc574b38..1a58d5b832a4 100644 --- a/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties +++ b/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties @@ -60,3 +60,9 @@ inline.property.confirmation=Inline property ''{0}'' with value ''{1}''? alpha.unsorted.properties.file.inspection.display.name=Properties File or Resource Bundle is Alphabetically Unsorted trailing.spaces.in.property.inspection.ignore.visible.spaces=Ignore visible whitespaces + +resource.bundle.contains.locales.with.suspicious.locale.languages.desciptor=Resource bundle contains locales with suspicious locale languages +dissociate.resource.bundle.quick.fix.name=Dissociate Resource Bundle +dissociate.resource.bundle.quick.fix.options.label=Additional language codes\: +dissociate.resource.bundle.quick.fix.options.input.text=Inter language code +dissociate.resource.bundle.quick.fix.options.input.title=Additional Locale Languages diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java index 5d8487d468a2..626961e8b9f2 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java @@ -47,7 +47,7 @@ import java.util.regex.Matcher; }) public class ResourceBundleManager implements PersistentStateComponent { private final static Logger LOG = Logger.getInstance(ResourceBundleManager.class); - private final static Locale DEFAULT_LOCALE = new Locale("", "", ""); + public final static Locale DEFAULT_LOCALE = new Locale("", "", ""); private ResourceBundleManagerState myState = new ResourceBundleManagerState(); @@ -172,7 +172,11 @@ public class ResourceBundleManager implements PersistentStateComponent resourceBundles = extractResourceBundles(e); assert resourceBundles.size() > 0; - final FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); - for (ResourceBundle resourceBundle : resourceBundles) { - fileEditorManager.closeFile(new ResourceBundleAsVirtualFile(resourceBundle)); - for (final PropertiesFile propertiesFile : resourceBundle.getPropertiesFiles()) { - fileEditorManager.closeFile(propertiesFile.getVirtualFile()); - } - ResourceBundleManager.getInstance(e.getProject()).dissociateResourceBundle(resourceBundle); - } - ProjectView.getInstance(project).refresh(); + dissociate(resourceBundles, project); } @Override @@ -79,6 +75,26 @@ public class DissociateResourceBundleAction extends AnAction { } } + public static void dissociate(final Collection resourceBundles, final Project project) { + final FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); + final Set toUpdateInProjectView = new HashSet(); + for (ResourceBundle resourceBundle : resourceBundles) { + fileEditorManager.closeFile(new ResourceBundleAsVirtualFile(resourceBundle)); + for (final PropertiesFile propertiesFile : resourceBundle.getPropertiesFiles()) { + fileEditorManager.closeFile(propertiesFile.getVirtualFile()); + PsiDirectory containingDirectory = propertiesFile.getContainingFile().getContainingDirectory(); + if (containingDirectory != null) { + toUpdateInProjectView.add(containingDirectory); + } + } + ResourceBundleManager.getInstance(project).dissociateResourceBundle(resourceBundle); + } + AbstractTreeBuilder treeBuilder = ProjectView.getInstance(project).getCurrentProjectViewPane().getTreeBuilder(); + for (PsiFileSystemItem item : toUpdateInProjectView) { + treeBuilder.queueUpdateFrom(item, false); + } + } + @NotNull private static Collection extractResourceBundles(final AnActionEvent event) { final Set targetResourceBundles = new HashSet(); diff --git a/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleNode.java b/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleNode.java index b9f61643095d..20af8439004c 100644 --- a/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleNode.java +++ b/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleNode.java @@ -32,6 +32,7 @@ import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.OpenFileDescriptor; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; @@ -97,4 +98,12 @@ public class ResourceBundleNode extends ProjectViewNode{ public Comparable getTypeSortKey() { return new PsiFileNode.ExtensionSortKey(StdFileTypes.PROPERTIES.getDefaultExtension()); } + + @Override + public boolean validate() { + if (!super.validate()) { + return false; + } + return Comparing.equal(getValue().getDefaultPropertiesFile().getResourceBundle(), getValue()); + } } diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java index cd2c6e2f0b4d..e39f45f1b3a9 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java @@ -488,7 +488,7 @@ public class RemoteDebugger implements ProcessDebugger { private StringBuilder myTextBuilder = new StringBuilder(); private DebuggerReader(final InputStream stream) throws IOException { - super(stream, CharsetToolkit.UTF8_CHARSET); //TODO: correct encoding? + super(stream, CharsetToolkit.UTF8_CHARSET, SleepingPolicy.BLOCKING); //TODO: correct encoding? start(); } diff --git a/resources-en/src/inspectionDescriptions/SuspiciousLocalesLanguages.html b/resources-en/src/inspectionDescriptions/SuspiciousLocalesLanguages.html new file mode 100644 index 000000000000..3e24e5e5951e --- /dev/null +++ b/resources-en/src/inspectionDescriptions/SuspiciousLocalesLanguages.html @@ -0,0 +1,5 @@ + + +Inspection detects locales which contain language codes not supported by Java. + + \ No newline at end of file