diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties index 5d11d6ae4daa..3861cf1bee4a 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties @@ -913,7 +913,7 @@ utility.class.without.private.constructor.problem.descriptor=Class #ref#ref() overrides concrete method #loc abstract.method.with.missing.implementations.problem.descriptor=Abstract method #ref() is not implemented in every subclass #loc abstract.method.overrides.abstract.method.problem.descriptor=Abstract method #ref() overrides abstract method #loc -abstract.method.overrides.abstract.method.ignore.different.javadoc.option=Ignore methods with different JavaDoc than their super methods +abstract.method.overrides.abstract.method.ignore.different.javadoc.option=Ignore methods with different Javadoc than their super methods abstract.method.overrides.abstract.method.ignore.different.annotations.option=Ignore methods with different annotations than their super methods abstract.class.extends.concrete.class.problem.descriptor=Class #ref is declared 'abstract', and extends a concrete class #loc static.non.final.field.problem.descriptor='static' non-'final' field #ref #loc @@ -932,7 +932,9 @@ marker.interface.problem.descriptor=Marker interface #ref #loc field.has.setter.but.no.getter.problem.descriptor=Field #ref has setter but no getter #loc abstract.class.never.implemented.problem.descriptor=Abstract class #ref has no concrete subclass #loc interface.never.implemented.problem.descriptor=Interface #ref has no concrete subclass #loc -missing.deprecated.annotation.problem.descriptor=Missing '@Deprecated' annotation on #ref() #loc +missing.deprecated.annotation.problem.descriptor=Missing '@Deprecated' annotation #loc +missing.deprecated.tag.problem.descriptor=Missing '@deprecated' Javadoc tag explanation #loc +missing.deprecated.tag.option=Warn on missing @deprecated Javadoc tag explanation missing.override.annotation.problem.descriptor=Missing '@Override' annotation on #ref() #loc non.thread.safe.lazy.initialization.problem.descriptor=Lazy initialization of 'static' field #ref is not thread-safe #loc empty.catch.block.problem.descriptor=Empty #ref block #loc diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/MissingDeprecatedAnnotationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/MissingDeprecatedAnnotationInspection.java index 869a707c6a0c..3a0898245916 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/MissingDeprecatedAnnotationInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javadoc/MissingDeprecatedAnnotationInspection.java @@ -16,6 +16,7 @@ package com.siyeh.ig.javadoc; import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.javadoc.PsiDocComment; @@ -26,9 +27,14 @@ import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.InspectionGadgetsFix; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; public class MissingDeprecatedAnnotationInspection extends BaseInspection { + @SuppressWarnings("PublicField") public boolean warnOnMissingJavadoc = false; + @Override @NotNull public String getDisplayName() { @@ -38,7 +44,17 @@ public class MissingDeprecatedAnnotationInspection extends BaseInspection { @Override @NotNull protected String buildErrorString(Object... infos) { - return InspectionGadgetsBundle.message("missing.deprecated.annotation.problem.descriptor"); + final boolean annotationWarning = ((Boolean)infos[0]).booleanValue(); + return annotationWarning + ? InspectionGadgetsBundle.message("missing.deprecated.annotation.problem.descriptor") + : InspectionGadgetsBundle.message("missing.deprecated.tag.problem.descriptor"); + } + + @Nullable + @Override + public JComponent createOptionsPanel() { + return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("missing.deprecated.tag.option"), + this, "warnOnMissingJavadoc"); } @Override @@ -48,6 +64,10 @@ public class MissingDeprecatedAnnotationInspection extends BaseInspection { @Override protected InspectionGadgetsFix buildFix(Object... infos) { + final boolean annotationWarning = ((Boolean)infos[0]).booleanValue(); + if (!annotationWarning) { + return null; + } return new MissingDeprecatedAnnotationFix(); } @@ -87,7 +107,7 @@ public class MissingDeprecatedAnnotationInspection extends BaseInspection { return new MissingDeprecatedAnnotationVisitor(); } - private static class MissingDeprecatedAnnotationVisitor extends BaseInspectionVisitor { + private class MissingDeprecatedAnnotationVisitor extends BaseInspectionVisitor { @Override public void visitClass(@NotNull PsiClass aClass) { @@ -95,10 +115,14 @@ public class MissingDeprecatedAnnotationInspection extends BaseInspection { if (!PsiUtil.isLanguageLevel5OrHigher(aClass)) { return; } - if (!hasDeprecatedComment(aClass) || hasDeprecatedAnnotation(aClass)) { - return; + if (hasDeprecatedAnnotation(aClass)) { + if (warnOnMissingJavadoc && !hasDeprecatedComment(aClass, true)) { + registerClassError(aClass, Boolean.FALSE); + } + } + else if (hasDeprecatedComment(aClass, false)) { + registerClassError(aClass, Boolean.TRUE); } - registerClassError(aClass); } @Override @@ -109,10 +133,14 @@ public class MissingDeprecatedAnnotationInspection extends BaseInspection { if (method.getNameIdentifier() == null) { return; } - if (!hasDeprecatedComment(method) || hasDeprecatedAnnotation(method)) { - return; + if (hasDeprecatedAnnotation(method)) { + if (warnOnMissingJavadoc && !hasDeprecatedComment(method, true)) { + registerMethodError(method, Boolean.FALSE); + } + } + else if (hasDeprecatedComment(method, false)) { + registerMethodError(method, Boolean.TRUE); } - registerMethodError(method); } @Override @@ -120,28 +148,31 @@ public class MissingDeprecatedAnnotationInspection extends BaseInspection { if (!PsiUtil.isLanguageLevel5OrHigher(field)) { return; } - if (!hasDeprecatedComment(field) || hasDeprecatedAnnotation(field)) { - return; + if (hasDeprecatedAnnotation(field)) { + if (warnOnMissingJavadoc && !hasDeprecatedComment(field, true)) { + registerFieldError(field, Boolean.FALSE); + } + } + else if (hasDeprecatedComment(field, false)) { + registerFieldError(field, Boolean.TRUE); } - registerFieldError(field); } - private static boolean hasDeprecatedAnnotation(PsiModifierListOwner element) { + private boolean hasDeprecatedAnnotation(PsiModifierListOwner element) { final PsiModifierList modifierList = element.getModifierList(); - if (modifierList == null) { - return false; - } - final PsiAnnotation annotation = modifierList.findAnnotation(CommonClassNames.JAVA_LANG_DEPRECATED); - return annotation != null; + return modifierList != null && modifierList.findAnnotation(CommonClassNames.JAVA_LANG_DEPRECATED) != null; } - private static boolean hasDeprecatedComment(PsiDocCommentOwner element) { + private boolean hasDeprecatedComment(PsiDocCommentOwner element, boolean checkContent) { final PsiDocComment comment = element.getDocComment(); if (comment == null) { return false; } final PsiDocTag deprecatedTag = comment.findTagByName("deprecated"); - return deprecatedTag != null; + if (deprecatedTag == null) { + return false; + } + return !checkContent || deprecatedTag.getValueElement() != null; } } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/MissingDeprecatedAnnotation.html b/plugins/InspectionGadgets/src/inspectionDescriptions/MissingDeprecatedAnnotation.html index 6ded6180ef1f..85d00c73f1f4 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/MissingDeprecatedAnnotation.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/MissingDeprecatedAnnotation.html @@ -7,6 +7,9 @@ This inspection only reports if the project or module is configured to use a language level of 5.0 or higher.

+Use the checkbox below to warn on symbols annotated with @Deprecated without a corresponding explanation in a +@deprecated Javadoc tag. +

\ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/javadoc/missing_deprecated_annotation/MissingDeprecatedAnnotation.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/javadoc/missing_deprecated_annotation/MissingDeprecatedAnnotation.java new file mode 100644 index 000000000000..7a8f181c93c9 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/javadoc/missing_deprecated_annotation/MissingDeprecatedAnnotation.java @@ -0,0 +1,37 @@ +/** + * @deprecated + */ +public class MissingDeprecatedAnnotation { + + /** + * @deprecated Use {@link #b()} instead + */ + @Deprecated + void a() {} + + /** + * @deprecated + */ + void b() {} + + /** + * @deprecated + */ + String s; + +} +@Deprecated +class Two { + + /** + * @deprecated + */ + @Deprecated + void a() {} + + @Deprecated + void b() {} + + @Deprecated + String s; +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/javadoc/MissingDeprecatedAnnotationInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/javadoc/MissingDeprecatedAnnotationInspectionTest.java new file mode 100644 index 000000000000..6b256a2c313d --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/javadoc/MissingDeprecatedAnnotationInspectionTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2014 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.siyeh.ig.javadoc; + +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.ig.LightInspectionTestCase; +import junit.framework.TestCase; +import org.jetbrains.annotations.Nullable; + +/** + * @author Bas Leijdekkers + */ +public class MissingDeprecatedAnnotationInspectionTest extends LightInspectionTestCase { + + public void testMissingDeprecatedAnnotation() { + doTest(); + } + + @Nullable + @Override + protected InspectionProfileEntry getInspection() { + final MissingDeprecatedAnnotationInspection inspection = new MissingDeprecatedAnnotationInspection(); + inspection.warnOnMissingJavadoc = true; + return inspection; + } +} \ No newline at end of file