Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ilya.Kazakevich
2015-05-07 19:00:02 +03:00
10 changed files with 136 additions and 29 deletions
@@ -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.
@@ -45,6 +45,7 @@ public abstract class AbstractCollectionComboBoxModel<T> extends AbstractListMod
public void setSelectedItem(@Nullable Object anItem) {
//noinspection unchecked
mySelection = (T)anItem;
update();
}
@Override
@@ -2332,8 +2332,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
UIUtil.drawLine(g, end.x, y1, end.x + charWidth - 1, y1);
}
else if (attributes.getEffectType() == EffectType.BOLD_LINE_UNDERSCORE) {
UIUtil.drawLine(g, end.x, y - 1, end.x + charWidth - 1, y - 1);
UIUtil.drawLine(g, end.x, y, end.x + charWidth - 1, y);
drawBoldLineUnderScore(g, end.x, y - 1, charWidth - 1);
}
else if (attributes.getEffectType() != EffectType.BOXED) {
UIUtil.drawLine(g, end.x, y, end.x + charWidth - 1, y);
@@ -2342,6 +2341,11 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
}
private static void drawBoldLineUnderScore(Graphics g, int x, int y, int width) {
int height = JBUI.scale(Registry.intValue("editor.bold.underline.height", 2));
g.fillRect(x, y, width, height);
}
@Override
public int getMaxWidthInRange(int startOffset, int endOffset) {
if (myUseNewRendering) return myView.getMaxWidthInRange(startOffset, endOffset);
@@ -3423,8 +3427,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
else if (effectType == EffectType.BOLD_LINE_UNDERSCORE) {
g.setColor(effectColor);
UIUtil.drawLine(g, xStart, y, xEnd, y);
UIUtil.drawLine(g, xStart, y + 1, xEnd, y + 1);
drawBoldLineUnderScore(g, xStart, y, xEnd-xStart);
g.setColor(savedColor);
}
else if (effectType == EffectType.STRIKEOUT) {
@@ -46,10 +46,7 @@ import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;
import java.awt.*;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.*;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ListIterator;
@@ -72,6 +69,22 @@ public abstract class SpeedSearchBase<Comp extends JComponent> extends SpeedSear
public SpeedSearchBase(Comp component) {
myComponent = component;
myComponent.addComponentListener(new ComponentAdapter() {
@Override
public void componentHidden(ComponentEvent event) {
manageSearchPopup(null);
}
@Override
public void componentMoved(ComponentEvent event) {
moveSearchPopup();
}
@Override
public void componentResized(ComponentEvent event) {
moveSearchPopup();
}
});
myComponent.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
@@ -568,7 +581,11 @@ public abstract class SpeedSearchBase<Comp extends JComponent> extends SpeedSear
return;
}
myPopupLayeredPane.add(mySearchPopup, JLayeredPane.POPUP_LAYER);
if (myPopupLayeredPane == null) return; // See # 27482. Somewho it does happen...
moveSearchPopup();
}
private void moveSearchPopup() {
if (myComponent == null || mySearchPopup == null || myPopupLayeredPane == null) return;
Point lPaneP = myPopupLayeredPane.getLocationOnScreen();
Point componentP = getComponentLocationOnScreen();
Rectangle r = getComponentVisibleRect();
@@ -539,6 +539,9 @@ editor.xcode.like.scrollbar.description=Enables auto-hideable Xcode-like editor
editor.config.stop.at.project.root=true
editor.config.stop.at.project.root.description=Stops searching for .editorconfig at project root (requires project reopening)
editor.bold.underline.height=2
editor.bold.underline.height.description=Underline height for EffectType.BOLD_LINE_UNDERSCORE
JDK8042508.bug.fixed=false
JDK8042508.bug.fixed.description=Disable check for type variable until javac bug is fixed
@@ -188,7 +188,9 @@ public class Foundation {
public static String getEncodingName(long nsStringEncoding) {
long cfEncoding = myFoundationLibrary.CFStringConvertNSStringEncodingToEncoding(nsStringEncoding);
ID pointer = myFoundationLibrary.CFStringConvertEncodingToIANACharSetName(cfEncoding);
return toStringViaUTF8(pointer);
String name = toStringViaUTF8(pointer);
if ("macintosh".equals(name)) name = "MacRoman"; // JDK8 does not recognize IANA's "macintosh" alias
return name;
}
public static long getEncodingCode(@Nullable String encodingName) {
@@ -16,15 +16,14 @@
package com.intellij.util.lang;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.io.URLUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import sun.misc.Resource;
import java.io.File;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
@@ -53,13 +52,8 @@ class JarLoader extends Loader {
}
}
private File getFileUrl() throws IOException {
try {
return new File(myURL.toURI());
}
catch (URISyntaxException e) {
throw new IOException(e);
}
private String getFileUrl() throws IOException {
return FileUtil.unquote(myURL.getFile());
}
@NotNull
@@ -16,12 +16,11 @@
package com.siyeh.ig.psiutils;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.*;
public class SynchronizationUtil {
private SynchronizationUtil() {
}
private SynchronizationUtil() {}
public static boolean isInSynchronizedContext(PsiElement element) {
final PsiElement context =
@@ -29,10 +28,61 @@ public class SynchronizationUtil {
if (context instanceof PsiSynchronizedStatement) {
return true;
}
if (!(context instanceof PsiMethod)) {
if (context instanceof PsiMethod) {
final PsiModifierListOwner modifierListOwner = (PsiModifierListOwner)context;
if (modifierListOwner.hasModifierProperty(PsiModifier.SYNCHRONIZED)) {
return true;
}
}
if (context instanceof PsiMethod || context instanceof PsiLambdaExpression) {
final HoldsLockAssertionVisitor visitor = new HoldsLockAssertionVisitor();
context.accept(visitor);
final PsiAssertStatement assertStatement = visitor.getAssertStatement();
return assertStatement != null && assertStatement.getTextOffset() + assertStatement.getTextLength() < element.getTextOffset();
}
return false;
}
public static boolean isCallToHoldsLock(PsiExpression expression) {
expression = ParenthesesUtils.stripParentheses(expression);
if (!(expression instanceof PsiMethodCallExpression)) {
return false;
}
final PsiModifierListOwner modifierListOwner = (PsiModifierListOwner)context;
return modifierListOwner.hasModifierProperty(PsiModifier.SYNCHRONIZED);
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
final String name = methodExpression.getReferenceName();
if (!"holdsLock".equals(name)) {
return false;
}
final PsiMethod method = methodCallExpression.resolveMethod();
if (method == null) {
return false;
}
final PsiClass aClass = method.getContainingClass();
return com.intellij.psi.util.InheritanceUtil.isInheritor(aClass, "java.lang.Thread");
}
private static class HoldsLockAssertionVisitor extends JavaRecursiveElementVisitor {
private PsiAssertStatement myAssertStatement = null;
@Override
public void visitAssertStatement(PsiAssertStatement statement) {
if (myAssertStatement != null) return;
super.visitAssertStatement(statement);
final PsiExpression condition = statement.getAssertCondition();
if (isCallToHoldsLock(condition)) {
myAssertStatement = statement;
}
}
@Override
public void visitElement(PsiElement element) {
if (myAssertStatement != null) return;
super.visitElement(element);
}
public PsiAssertStatement getAssertStatement() {
return myAssertStatement;
}
}
}
@@ -21,6 +21,7 @@ import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PropertyUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.HashMap;
import com.siyeh.ig.psiutils.SynchronizationUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
@@ -61,6 +62,14 @@ class VariableAccessVisitor extends JavaRecursiveElementVisitor {
m_inSynchronizedContext = wasInSync;
}
@Override
public void visitLambdaExpression(PsiLambdaExpression expression) {
final boolean wasInSync = m_inSynchronizedContext;
m_inSynchronizedContext = false;
super.visitLambdaExpression(expression);
m_inSynchronizedContext = wasInSync;
}
@Override
public void visitReferenceExpression(@NotNull PsiReferenceExpression ref) {
super.visitReferenceExpression(ref);
@@ -128,6 +137,15 @@ class VariableAccessVisitor extends JavaRecursiveElementVisitor {
m_inSynchronizedContext = wasInSync;
}
@Override
public void visitAssertStatement(PsiAssertStatement statement) {
final PsiExpression condition = statement.getAssertCondition();
if (SynchronizationUtil.isCallToHoldsLock(condition)) {
m_inSynchronizedContext = true;
}
super.visitAssertStatement(statement);
}
@Override
public void visitMethod(@NotNull PsiMethod method) {
if (method.hasModifierProperty(PsiModifier.PRIVATE)) {
@@ -3,12 +3,16 @@ package com.siyeh.igtest.threading.call_to_native_method_while_locked;
public class CallToNativeMethodWhileLocked {
synchronized void a() {
Double.<warning descr="Call to native method 'doubleToLongBits()' in a synchronized context">doubleToLongBits</warning>(9.7);
Double.<warning descr="Call to native method 'doubleToRawLongBits()' in a synchronized context">doubleToRawLongBits</warning>(9.7);
Runnable r = () -> {
Double.doubleToLongBits(123.4);
Double.doubleToRawLongBits(123.4);
};
new Object() {
long l = Double.doubleToLongBits(42.0);
long l = Double.doubleToRawLongBits(42.0);
};
Runnable s = () -> {
assert Thread.holdsLock(this);
Double.<warning descr="Call to native method 'doubleToRawLongBits()' in a synchronized context">doubleToRawLongBits</warning>(40.0);
};
}
}
@@ -4,12 +4,16 @@ public class FieldAccessedSynchronizedAndUnsynchronized
{
private final Object m_lock = new Object();
private Object <warning descr="Field 'm_contents' is accessed in both synchronized and unsynchronized contexts">m_contents</warning> = new Object();
private Object <warning descr="Field 'a' is accessed in both synchronized and unsynchronized contexts">a</warning>;
private Object b;
public void foo()
{
synchronized(m_lock)
{
m_contents = new Object();
a = new Object();
b = new Object();
}
getContents();
}
@@ -24,6 +28,17 @@ public class FieldAccessedSynchronizedAndUnsynchronized
getContents();
}
public synchronized void g() {
Runnable r = () -> {
System.out.println(a);
};
}
public void h() {
assert Thread.holdsLock(m_lock);
System.out.println(b);
}
}
class Test {
private Object <warning descr="Field 'object' is accessed in both synchronized and unsynchronized contexts">object</warning>;