mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEADEV-41150 (new "ThreadLocal should be static final" inspection)
This commit is contained in:
@@ -1685,7 +1685,7 @@ logger.initialized.with.foreign.class.quickfix=Replace with ''{0}.class''
|
||||
logger.initialized.with.foreign.class.problem.descriptor=Logger initializer with foreign class <code>#ref</code> #loc
|
||||
logger.initialized.with.foreign.class.display.name=Logger initialized with foreign class
|
||||
logger.factory.method.name=Logger factory &method:
|
||||
non.constant.logger.quickfix=Make 'static final'
|
||||
make.static.final.quickfix=Make ''{0}'' static final
|
||||
logging.condition.disagrees.with.log.statement.display.name=Logging condition does not match log statement
|
||||
logging.condition.disagrees.with.log.statement.problem.descriptor=Logging condition <code>#ref()</code> does not match ''{0}()'' log statement #loc
|
||||
log.statement.guarded.by.log.condition.display.name=Log statement not guarded by log condition
|
||||
@@ -1752,4 +1752,6 @@ multiple.exceptions.declared.on.test.method.problem.descriptor=<code>#ref</code>
|
||||
multiple.exceptions.declared.on.test.method.quickfix=Replace with 'throws Exception'
|
||||
unnecessary.javadoc.link.display.name=Unnecessary JavaDoc link
|
||||
unnecessary.javadoc.link.problem.descriptor=<code>#ref</code> is unnecessary
|
||||
unnecessary.javadoc.link.quickfix=Remove unnecessary {0}
|
||||
unnecessary.javadoc.link.quickfix=Remove unnecessary {0}
|
||||
thread.local.not.static.final.display.name=ThreadLocal field not declared static final
|
||||
thread.local.not.static.final.problem.descriptor=ThreadLocal <code>#ref</code> is not declared 'static final'
|
||||
@@ -849,6 +849,7 @@ public class InspectionGadgetsPlugin implements ApplicationComponent,
|
||||
m_inspectionClasses.add(SynchronizeOnThisInspection.class);
|
||||
m_inspectionClasses.add(SynchronizedMethodInspection.class);
|
||||
m_inspectionClasses.add(SystemRunFinalizersOnExitInspection.class);
|
||||
m_inspectionClasses.add(ThreadLocalNotStaticFinalInspection.class);
|
||||
m_inspectionClasses.add(ThreadPriorityInspection.class);
|
||||
m_inspectionClasses.add(ThreadRunInspection.class);
|
||||
m_inspectionClasses.add(ThreadStartInConstructionInspection.class);
|
||||
|
||||
@@ -18,13 +18,10 @@ package com.siyeh.ig.fixes;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.Query;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.InspectionGadgetsFix;
|
||||
import com.siyeh.ig.psiutils.FinalUtils;
|
||||
import com.siyeh.ig.psiutils.InitializationUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -39,11 +36,7 @@ public class MakeFieldFinalFix extends InspectionGadgetsFix {
|
||||
|
||||
@Nullable
|
||||
public static InspectionGadgetsFix buildFix(PsiField field) {
|
||||
if (field.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
if (!canStaticFieldBeFinal(field)) {
|
||||
return null;
|
||||
}
|
||||
} else if (!canInstanceFieldBeFinal(field)) {
|
||||
if (!FinalUtils.canFieldBeFinal(field)) {
|
||||
return null;
|
||||
}
|
||||
final String name = field.getName();
|
||||
@@ -55,77 +48,6 @@ public class MakeFieldFinalFix extends InspectionGadgetsFix {
|
||||
return new MakeFieldFinalFix(field.getName());
|
||||
}
|
||||
|
||||
private static boolean canStaticFieldBeFinal(PsiField field) {
|
||||
final boolean hasInitializer = field.hasInitializer();
|
||||
final boolean initializedInOneStaticInitializer =
|
||||
isInitializedInOneStaticInitializer(field);
|
||||
if (hasInitializer) {
|
||||
if (initializedInOneStaticInitializer) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!initializedInOneStaticInitializer) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
final Query<PsiReference> query = ReferencesSearch.search(field);
|
||||
for (PsiReference reference : query) {
|
||||
final PsiElement element = reference.getElement();
|
||||
if (!(element instanceof PsiExpression)) {
|
||||
continue;
|
||||
}
|
||||
final PsiExpression expression = (PsiExpression) element;
|
||||
if (!PsiUtil.isOnAssignmentLeftHand(expression)) {
|
||||
continue;
|
||||
}
|
||||
final PsiMethod method = PsiTreeUtil.getParentOfType(
|
||||
expression, PsiMethod.class);
|
||||
if (method != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean canInstanceFieldBeFinal(PsiField field) {
|
||||
final boolean hasInitializer = field.hasInitializer();
|
||||
final boolean initializedInOneInitializer =
|
||||
isInitializedInOneInitializer(field);
|
||||
final boolean initializedInConstructors =
|
||||
isInitializedInConstructors(field);
|
||||
if (hasInitializer) {
|
||||
if (initializedInOneInitializer) {
|
||||
return false;
|
||||
}
|
||||
if (initializedInConstructors) {
|
||||
return false;
|
||||
}
|
||||
} else if (initializedInOneInitializer) {
|
||||
if (initializedInConstructors) {
|
||||
return false;
|
||||
}
|
||||
} else if (!initializedInConstructors) {
|
||||
return false;
|
||||
}
|
||||
final Query<PsiReference> query = ReferencesSearch.search(field);
|
||||
for (PsiReference reference : query) {
|
||||
final PsiElement element = reference.getElement();
|
||||
if (!(element instanceof PsiExpression)) {
|
||||
continue;
|
||||
}
|
||||
final PsiExpression expression = (PsiExpression) element;
|
||||
if (!PsiUtil.isOnAssignmentLeftHand(expression)) {
|
||||
continue;
|
||||
}
|
||||
final PsiMethod method = PsiTreeUtil.getParentOfType(
|
||||
expression, PsiMethod.class);
|
||||
if (method != null && !method.isConstructor()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return InspectionGadgetsBundle.message("make.field.final.quickfix",
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2003-2009 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* 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.siyeh.ig.fixes;
|
||||
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.InspectionGadgetsFix;
|
||||
import com.siyeh.ig.psiutils.FinalUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class MakeFieldStaticFinalFix extends InspectionGadgetsFix {
|
||||
|
||||
private final String fieldName;
|
||||
|
||||
private MakeFieldStaticFinalFix(String fieldName) {
|
||||
this.fieldName = fieldName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static InspectionGadgetsFix buildFixUnconditional(
|
||||
@NotNull PsiField field) {
|
||||
return new MakeFieldStaticFinalFix(field.getName());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static InspectionGadgetsFix buildFix(PsiField field) {
|
||||
final PsiExpression initializer = field.getInitializer();
|
||||
if (initializer == null) {
|
||||
return null;
|
||||
}
|
||||
if (!FinalUtils.canFieldBeFinal(field)) {
|
||||
return null;
|
||||
}
|
||||
return new MakeFieldStaticFinalFix(field.getName());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"make.static.final.quickfix", fieldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFix(Project project, ProblemDescriptor descriptor)
|
||||
throws IncorrectOperationException {
|
||||
final PsiElement element = descriptor.getPsiElement();
|
||||
final PsiElement parent = element.getParent();
|
||||
if (!(parent instanceof PsiField)) {
|
||||
return;
|
||||
}
|
||||
final PsiField field = (PsiField) parent;
|
||||
final PsiModifierList modifierList = field.getModifierList();
|
||||
if (modifierList == null) {
|
||||
return;
|
||||
}
|
||||
modifierList.setModifierProperty(PsiModifier.FINAL, true);
|
||||
modifierList.setModifierProperty(PsiModifier.STATIC, true);
|
||||
}
|
||||
}
|
||||
+18
-37
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2008 Dave Griffith, Bas Leijdekkers
|
||||
* Copyright 2003-2009 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,14 +16,12 @@
|
||||
package com.siyeh.ig.logging;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.RegExInputVerifier;
|
||||
import com.siyeh.ig.InspectionGadgetsFix;
|
||||
import com.siyeh.ig.fixes.MakeFieldStaticFinalFix;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -37,17 +35,20 @@ public class NonStaticFinalLoggerInspection extends BaseInspection {
|
||||
/** @noinspection PublicField*/
|
||||
public String loggerClassName = "java.util.logging.Logger";
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getID(){
|
||||
return "NonConstantLogger";
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getDisplayName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"non.constant.logger.display.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
protected String buildErrorString(Object... infos) {
|
||||
return InspectionGadgetsBundle.message(
|
||||
@@ -56,35 +57,12 @@ public class NonStaticFinalLoggerInspection extends BaseInspection {
|
||||
|
||||
@Override
|
||||
protected InspectionGadgetsFix buildFix(Object... infos) {
|
||||
return new NonStaticFinalLoggerFix();
|
||||
}
|
||||
|
||||
private static class NonStaticFinalLoggerFix extends InspectionGadgetsFix {
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"non.constant.logger.quickfix");
|
||||
}
|
||||
|
||||
protected void doFix(Project project, ProblemDescriptor descriptor)
|
||||
throws IncorrectOperationException {
|
||||
final PsiElement element = descriptor.getPsiElement();
|
||||
final PsiElement parent = element.getParent();
|
||||
if (!(parent instanceof PsiField)) {
|
||||
return;
|
||||
}
|
||||
PsiField field = (PsiField) parent;
|
||||
final PsiModifierList modifierList = field.getModifierList();
|
||||
if (modifierList == null) {
|
||||
return;
|
||||
}
|
||||
modifierList.setModifierProperty(PsiModifier.FINAL, true);
|
||||
modifierList.setModifierProperty(PsiModifier.STATIC, true);
|
||||
}
|
||||
final PsiField field = (PsiField) infos[0];
|
||||
return MakeFieldStaticFinalFix.buildFixUnconditional(field);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public JComponent createOptionsPanel() {
|
||||
final GridBagLayout layout = new GridBagLayout();
|
||||
final JPanel panel = new JPanel(layout);
|
||||
@@ -137,6 +115,7 @@ public class NonStaticFinalLoggerInspection extends BaseInspection {
|
||||
return panel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseInspectionVisitor buildVisitor() {
|
||||
return new NonStaticFinalLoggerVisitor();
|
||||
}
|
||||
@@ -157,17 +136,19 @@ public class NonStaticFinalLoggerInspection extends BaseInspection {
|
||||
}
|
||||
final PsiField[] fields = aClass.getFields();
|
||||
for(final PsiField field : fields) {
|
||||
if(isLogger(field)) {
|
||||
if(!field.hasModifierProperty(PsiModifier.STATIC) ||
|
||||
!field.hasModifierProperty(PsiModifier.FINAL)){
|
||||
registerFieldError(field);
|
||||
}
|
||||
if (!isLogger(field)) {
|
||||
continue;
|
||||
}
|
||||
if (field.hasModifierProperty(PsiModifier.STATIC) &&
|
||||
field.hasModifierProperty(PsiModifier.FINAL)) {
|
||||
continue;
|
||||
}
|
||||
registerFieldError(field, field);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isLogger(PsiField field) {
|
||||
final PsiType type = field.getType();
|
||||
private boolean isLogger(PsiVariable variable) {
|
||||
final PsiType type = variable.getType();
|
||||
final String text = type.getCanonicalText();
|
||||
return text.equals(loggerClassName);
|
||||
}
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2009 Bas Leijdekkers
|
||||
*
|
||||
* 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.siyeh.ig.threading;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.InspectionGadgetsBundle;import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.InspectionGadgetsFix;
|
||||
import com.siyeh.ig.fixes.MakeFieldStaticFinalFix;
|
||||
import com.siyeh.ig.psiutils.ClassUtils;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ThreadLocalNotStaticFinalInspection extends BaseInspection {
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"thread.local.not.static.final.display.name");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String buildErrorString(Object... infos) {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"thread.local.not.static.final.problem.descriptor");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InspectionGadgetsFix buildFix(Object... infos) {
|
||||
return MakeFieldStaticFinalFix.buildFix((PsiField) infos[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseInspectionVisitor buildVisitor() {
|
||||
return new ThreadLocalNotStaticFinalVisitor();
|
||||
}
|
||||
|
||||
private static class ThreadLocalNotStaticFinalVisitor
|
||||
extends BaseInspectionVisitor {
|
||||
|
||||
@Override
|
||||
public void visitField(PsiField field) {
|
||||
super.visitField(field);
|
||||
final PsiType type = field.getType();
|
||||
if (!(type instanceof PsiClassType)) {
|
||||
return;
|
||||
}
|
||||
final PsiClassType classType = (PsiClassType)type;
|
||||
final PsiClass aClass = classType.resolve();
|
||||
if (aClass == null) {
|
||||
return;
|
||||
}
|
||||
if (!ClassUtils.isSubclass(aClass, "java.lang.ThreadLocal")) {
|
||||
return;
|
||||
}
|
||||
final PsiModifierList modifierList = field.getModifierList();
|
||||
if (modifierList == null) {
|
||||
return;
|
||||
}
|
||||
if (modifierList.hasModifierProperty(PsiModifier.STATIC) &&
|
||||
modifierList.hasModifierProperty(PsiModifier.FINAL)) {
|
||||
return;
|
||||
}
|
||||
registerFieldError(field, field);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<html>
|
||||
<body><table> <tr> <td valign="top" height="150">
|
||||
<font face="verdana" size="-1">
|
||||
In the most common case a <b><font color="#000080">java.lang.ThreadLocal</font></b> instance
|
||||
associates state with a thread. A non-static non-final
|
||||
<b><font color="#000080">java.lang.ThreadLocal</font></b> field associates state with
|
||||
an instance-thread combination. This is seldom necessary and often a bug
|
||||
which can cause memory leaks and possibly incorrect behavior.
|
||||
<p>
|
||||
This inspection has a quick fix to make the field <b><font color="#000080">static final</font></b>
|
||||
</p>
|
||||
</font></td> </tr> <tr> <td height="20"> <font face="verdana" size="-2">New in 9, Powered by InspectionGadgets </font> </td> </tr> </table> </body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user