diff --git a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties index cf6ea5d01e0f..cc8d79c0fe91 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties @@ -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 #ref #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 #ref() 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=#ref multiple.exceptions.declared.on.test.method.quickfix=Replace with 'throws Exception' unnecessary.javadoc.link.display.name=Unnecessary JavaDoc link unnecessary.javadoc.link.problem.descriptor=#ref is unnecessary -unnecessary.javadoc.link.quickfix=Remove unnecessary {0} \ No newline at end of file +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 #ref is not declared 'static final' \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionGadgetsPlugin.java b/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionGadgetsPlugin.java index 9a754af755f5..3c56e8439c0f 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionGadgetsPlugin.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionGadgetsPlugin.java @@ -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); diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MakeFieldFinalFix.java b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MakeFieldFinalFix.java index dbf6070944fe..fde37f045023 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MakeFieldFinalFix.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MakeFieldFinalFix.java @@ -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 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 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", diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MakeFieldStaticFinalFix.java b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MakeFieldStaticFinalFix.java new file mode 100644 index 000000000000..3134881ccdc1 --- /dev/null +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MakeFieldStaticFinalFix.java @@ -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); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/logging/NonStaticFinalLoggerInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/logging/NonStaticFinalLoggerInspection.java index 106bb4410463..f6c2e83521c5 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/logging/NonStaticFinalLoggerInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/logging/NonStaticFinalLoggerInspection.java @@ -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); } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/threading/ThreadLocalNotStaticFinalInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/threading/ThreadLocalNotStaticFinalInspection.java new file mode 100644 index 000000000000..df7ed165308e --- /dev/null +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/threading/ThreadLocalNotStaticFinalInspection.java @@ -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); + } + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ThreadLocalNotStaticFinal.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ThreadLocalNotStaticFinal.html new file mode 100644 index 000000000000..dc909d345188 --- /dev/null +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ThreadLocalNotStaticFinal.html @@ -0,0 +1,13 @@ + +
+ +In the most common case a java.lang.ThreadLocal instance +associates state with a thread. A non-static non-final +java.lang.ThreadLocal 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. +

+This inspection has a quick fix to make the field static final +

+
New in 9, Powered by InspectionGadgets
+ \ No newline at end of file