Merge remote-tracking branch 'origin/master'

This commit is contained in:
Sergey Malenkov
2015-05-07 18:09:04 +03:00
11 changed files with 136 additions and 25 deletions
@@ -81,7 +81,7 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable
public static final String DISPLAY_NAME = "Inspections";
private static final String HEADER_TITLE = "Profile:";
private static final Logger LOG = Logger.getInstance("#" + InspectionToolsConfigurable.class.getName());
private static final Logger LOG = Logger.getInstance(InspectionToolsConfigurable.class);
protected final InspectionProfileManager myProfileManager;
protected final InspectionProjectProfileManager myProjectProfileManager;
private final CardLayout myLayout = new CardLayout();
@@ -111,7 +111,12 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable
myProfiles = new ProfilesConfigurableComboBox(new ListCellRendererWrapper<Profile>() {
@Override
public void customize(final JList list, final Profile value, final int index, final boolean selected, final boolean hasFocus) {
final SingleInspectionProfilePanel singleInspectionProfilePanel = myPanels.get(value);
final SingleInspectionProfilePanel singleInspectionProfilePanel = getProfilePanel(value);
LOG.assertTrue(singleInspectionProfilePanel != null,
String.format("No panel for profile (name = %s, manager class = %s, is modified = %s) found",
value.getName(),
value.getProfileManager().getClass(),
((InspectionProfileImpl) value).isChanged()));
final boolean isShared = singleInspectionProfilePanel.isProfileShared();
setIcon(isShared ? AllIcons.General.ProjectSettings : AllIcons.General.Settings);
setText(singleInspectionProfilePanel.getCurrentProfileName());
@@ -91,7 +91,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
"*.hprof;*.pyc;*.pyo;*.rbc;*~;.DS_Store;.bundle;.git;.hg;.svn;CVS;RCS;SCCS;__pycache__;.tox;_svn;rcs;vssver.scc;vssver2.scc;";
private static boolean RE_DETECT_ASYNC = !ApplicationManager.getApplication().isUnitTestMode();
private final Collection<FileType> myDefaultTypes = new THashSet<FileType>();
private final Set<FileType> myDefaultTypes = new THashSet<FileType>();
private final List<FileTypeIdentifiableByVirtualFile> mySpecialFileTypes = new ArrayList<FileTypeIdentifiableByVirtualFile>();
private FileTypeAssocTable<FileType> myPatternsTable = new FileTypeAssocTable<FileType>();
@@ -1007,7 +1007,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent
List<FileType> notExternalizableFileTypes = new ArrayList<FileType>();
for (FileType type : mySchemesManager.getAllSchemes()) {
if (!(type instanceof AbstractFileType)) {
if (!(type instanceof AbstractFileType) || myDefaultTypes.contains(type)) {
notExternalizableFileTypes.add(type);
}
}
@@ -306,9 +306,11 @@
</option>
<option name="WARNING_ATTRIBUTES">
<value>
<option name="EFFECT_COLOR" value="e68110" />
<option name="FOREGROUND"/>
<option name="BACKGROUND" value="f6ebbc"/>
<option name="EFFECT_COLOR"/>
<option name="EFFECT_TYPE" value="1"/>
<option name="ERROR_STRIPE_COLOR" value="ebc700" />
<option name="EFFECT_TYPE" value="2" />
</value>
</option>
<option name="GENERIC_SERVER_ERROR_OR_WARNING">
@@ -2579,9 +2581,9 @@
</option>
<option name="WARNING_ATTRIBUTES">
<value>
<option name="EFFECT_COLOR" value="af8000" />
<option name="ERROR_STRIPE_COLOR" value="be9117" />
<option name="BACKGROUND" value="52503a" />
<option name="EFFECT_TYPE" value="2" />
<option name="ERROR_STRIPE_COLOR" value="be9117" />
</value>
</option>
<option name="WRITE_IDENTIFIER_UNDER_CARET_ATTRIBUTES">
@@ -109,8 +109,9 @@ public class GeneralCommandLineTest {
File dir = FileUtil.createTempDirectory("path with spaces 'and quotes' и юникодом ", ".tmp");
try {
GeneralCommandLine commandLine = makeJavaCommand(ParamPassingTest.class, dir);
commandLine.addParameter("test");
String output = execAndGetOutput(commandLine, null);
assertEquals("=====\n=====\n", StringUtil.convertLineSeparators(output));
assertEquals("test\n", StringUtil.convertLineSeparators(output));
}
finally {
FileUtil.delete(dir);
@@ -351,7 +351,7 @@ public class FileTypesTest extends PlatformTestCase {
}
private static void log(String message) {
//System.out.println(message);
System.out.println(message);
}
private void ensureRedetected(VirtualFile vFile, Set<VirtualFile> detectorCalled) {
@@ -510,4 +510,18 @@ public class FileTypesTest extends PlatformTestCase {
fail(JDOMUtil.writeElement(map));
}
}
public void testDefaultFileType() throws Exception {
FileType idl = myFileTypeManager.findFileTypeByName("IDL");
myFileTypeManager.associatePattern(idl, "*.xxx");
Element element = myFileTypeManager.getState();
log(JDOMUtil.writeElement(element));
myFileTypeManager.removeAssociatedExtension(idl, "xxx");
myFileTypeManager.clearForTests();
myFileTypeManager.initStandardFileTypes();
myFileTypeManager.loadState(element);
myFileTypeManager.initComponent();
FileType extensions = myFileTypeManager.getFileTypeByExtension("xxx");
assertEquals("IDL", extensions.getName());
}
}
@@ -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,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>;
@@ -64,7 +64,7 @@ public class JUnitTreeByDescriptionHierarchyTest {
"##teamcity[enteredTheMatrix]\n" +
"##teamcity[rootName name = 'root']\n" +
"##teamcity[rootName name = 'root' location = 'java:suite://root']\n" +
"##teamcity[testSuiteFinished name='root']\n" +
"##teamcity[testSuiteStarted name ='TestA']\n" +
"##teamcity[testSuiteStarted name ='|[0|]']\n" +
@@ -108,7 +108,7 @@ public class JUnitTreeByDescriptionHierarchyTest {
"##teamcity[suiteTreeEnded name='|[1|]']\n",
//start
"##teamcity[enteredTheMatrix]\n" +
"##teamcity[rootName name = 'TestA' comment = 'a']\n" +
"##teamcity[rootName name = 'TestA' comment = 'a' location = 'java:suite://a.TestA']\n" +
"##teamcity[testSuiteStarted name ='|[0|]']\n" +
"##teamcity[testStarted name='testName|[0|]' locationHint='java:test://a.TestA.testName|[0|]']\n" +
"\n" +
@@ -153,7 +153,7 @@ public class JUnitTreeByDescriptionHierarchyTest {
//started
"##teamcity[enteredTheMatrix]\n" +
"##teamcity[rootName name = 'root']\n" +
"##teamcity[rootName name = 'root' location = 'java:suite://root']\n" +
"##teamcity[testSuiteFinished name='root']\n" +
"##teamcity[testSuiteStarted name ='ASuite1']\n" +
"##teamcity[testSuiteStarted name ='ATest']\n" +
@@ -232,7 +232,7 @@ public class JUnitTreeByDescriptionHierarchyTest {
//start
"##teamcity[enteredTheMatrix]\n" +
"##teamcity[rootName name = 'root']\n" +
"##teamcity[rootName name = 'root' location = 'java:suite://root']\n" +
"##teamcity[testSuiteFinished name='root']\n" +
"##teamcity[testSuiteStarted name ='ATest']\n" +
"##teamcity[testSuiteStarted name ='|[0|]']\n" +
@@ -288,7 +288,7 @@ public class JUnitTreeByDescriptionHierarchyTest {
"##teamcity[enteredTheMatrix]\n" +
"##teamcity[rootName name = 'TestA']\n" +
"##teamcity[rootName name = 'TestA' location = 'java:suite://TestA']\n" +
"##teamcity[testStarted name='warning' locationHint='java:test://junit.framework.TestSuite$1.warning']\n" +
"\n" +
"##teamcity[testFinished name='warning']\n" +