2020package org .sonar .java .checks ;
2121
2222import com .google .common .collect .ImmutableList ;
23+
2324import org .sonar .api .server .rule .RulesDefinition ;
2425import org .sonar .check .Priority ;
2526import org .sonar .check .Rule ;
3031import org .sonar .plugins .java .api .semantic .Symbol ;
3132import org .sonar .plugins .java .api .tree .AnnotationTree ;
3233import org .sonar .plugins .java .api .tree .Tree ;
34+ import org .sonar .plugins .java .api .tree .VariableTree ;
3335import org .sonar .squidbridge .annotations .ActivatedByDefault ;
3436import org .sonar .squidbridge .annotations .SqaleConstantRemediation ;
3537import org .sonar .squidbridge .annotations .SqaleSubCharacteristic ;
4648@ ActivatedByDefault
4749public class ChangeMethodContractCheck extends IssuableSubscriptionVisitor {
4850
51+ private static final String JAVAX_ANNOTATION_CHECK_FOR_NULL = "javax.annotation.CheckForNull" ;
52+ private static final String JAVAX_ANNOTATION_NULLABLE = "javax.annotation.Nullable" ;
53+ private static final String JAVAX_ANNOTATION_NONNULL = "javax.annotation.Nonnull" ;
54+
4955 @ Override
5056 public List <Tree .Kind > nodesToVisit () {
5157 return ImmutableList .of (Tree .Kind .METHOD );
@@ -65,36 +71,40 @@ public void visitNode(Tree tree) {
6571 }
6672
6773 private void checkContractChange (MethodTreeImpl methodTree , JavaSymbol .MethodJavaSymbol overridee ) {
68- if (methodTree .isEqualsMethod () && methodTree .parameters ().get (0 ).symbol ().metadata ().isAnnotatedWith ("javax.annotation.Nonnull" )) {
74+ if (methodTree .isEqualsMethod () && methodTree .parameters ().get (0 ).symbol ().metadata ().isAnnotatedWith (JAVAX_ANNOTATION_NONNULL )) {
6975 reportIssue (methodTree .parameters ().get (0 ), "Equals method should accept null parameters and return false." );
7076 return ;
7177 }
7278 for (int i = 0 ; i < methodTree .parameters ().size (); i ++) {
73- Symbol paramSymbol = methodTree .parameters ().get (i ). symbol ( );
79+ VariableTree parameter = methodTree .parameters ().get (i );
7480 Symbol overrideeParamSymbol = overridee .getParameters ().scopeSymbols ().get (i );
75- if (nonNullVsNull (paramSymbol , overrideeParamSymbol )) {
76- Tree reportTree = methodTree .parameters ().get (i );
77- for (AnnotationTree annotationTree : methodTree .parameters ().get (i ).modifiers ().annotations ()) {
78- if (annotationTree .symbolType ().is ("javax.annotation.Nonnull" )) {
79- reportTree = annotationTree ;
80- }
81- }
82- reportIssue (reportTree , "Remove this \" Nonnull\" annotation to honor the overridden method's contract." );
83- }
81+ checkParameter (parameter , overrideeParamSymbol );
8482 }
8583 if (nonNullVsNull (overridee , methodTree .symbol ())) {
8684 for (AnnotationTree annotationTree : methodTree .modifiers ().annotations ()) {
87- if (annotationTree .symbolType ().is ("javax.annotation.Nullable" ) || annotationTree .symbolType ().is ("javax.annotation.CheckForNull" )) {
85+ if (annotationTree .symbolType ().is (JAVAX_ANNOTATION_NULLABLE ) || annotationTree .symbolType ().is (JAVAX_ANNOTATION_CHECK_FOR_NULL )) {
8886 reportIssue (annotationTree , "Remove this \" " + annotationTree .symbolType ().name () +"\" annotation to honor the overridden method's contract." );
8987 }
9088 }
9189 }
9290 }
9391
92+ private void checkParameter (VariableTree parameter , Symbol overrideeParamSymbol ) {
93+ Tree reportTree = parameter ;
94+ if (nonNullVsNull (parameter .symbol (), overrideeParamSymbol )) {
95+ for (AnnotationTree annotationTree : parameter .modifiers ().annotations ()) {
96+ if (annotationTree .symbolType ().is (JAVAX_ANNOTATION_NONNULL )) {
97+ reportTree = annotationTree ;
98+ }
99+ }
100+ reportIssue (reportTree , "Remove this \" Nonnull\" annotation to honor the overridden method's contract." );
101+ }
102+ }
103+
94104 private static boolean nonNullVsNull (Symbol sym1 , Symbol sym2 ) {
95- return sym1 .metadata ().isAnnotatedWith ("javax.annotation.Nonnull" ) &&
96- (sym2 .metadata ().isAnnotatedWith ("javax.annotation.Nullable" )
97- || sym2 .metadata ().isAnnotatedWith ("javax.annotation.CheckForNull" ));
105+ return sym1 .metadata ().isAnnotatedWith (JAVAX_ANNOTATION_NONNULL ) &&
106+ (sym2 .metadata ().isAnnotatedWith (JAVAX_ANNOTATION_NULLABLE )
107+ || sym2 .metadata ().isAnnotatedWith (JAVAX_ANNOTATION_CHECK_FOR_NULL ));
98108
99109 }
100110
0 commit comments