1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.providers.media; 18 19 import static com.google.errorprone.BugPattern.SeverityLevel.WARNING; 20 21 import com.google.auto.service.AutoService; 22 import com.google.errorprone.BugPattern; 23 import com.google.errorprone.VisitorState; 24 import com.google.errorprone.bugpatterns.BugChecker; 25 import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher; 26 import com.google.errorprone.matchers.ChildMultiMatcher; 27 import com.google.errorprone.matchers.Description; 28 import com.google.errorprone.matchers.FieldMatchers; 29 import com.google.errorprone.matchers.Matcher; 30 import com.google.errorprone.matchers.Matchers; 31 import com.sun.source.tree.ExpressionTree; 32 import com.sun.source.tree.MethodInvocationTree; 33 34 @AutoService(BugChecker.class) 35 @BugPattern( 36 name = "MediaProviderLocaleRoot", 37 summary = "Verifies that all case-altering methods use Locale.ROOT", 38 severity = WARNING) 39 public final class LocaleRootChecker extends BugChecker implements MethodInvocationTreeMatcher { 40 private static final Matcher<ExpressionTree> STRING_TO_UPPER_CASE = 41 Matchers.instanceMethod().onExactClass("java.lang.String").named("toUpperCase"); 42 private static final Matcher<ExpressionTree> STRING_TO_LOWER_CASE = 43 Matchers.instanceMethod().onExactClass("java.lang.String").named("toLowerCase"); 44 private static final Matcher<ExpressionTree> LOCALE_ROOT = 45 FieldMatchers.staticField("java.util.Locale", "ROOT"); 46 47 private static final Matcher<ExpressionTree> MISSING_LOCALE_ROOT = Matchers.anyOf( 48 Matchers.methodInvocation( 49 STRING_TO_UPPER_CASE, 50 ChildMultiMatcher.MatchType.ALL, 51 Matchers.anyOf(Matchers.nothing(), Matchers.not(LOCALE_ROOT))), 52 Matchers.methodInvocation( 53 STRING_TO_LOWER_CASE, 54 ChildMultiMatcher.MatchType.ALL, 55 Matchers.anyOf(Matchers.nothing(), Matchers.not(LOCALE_ROOT))) 56 ); 57 58 @Override matchMethodInvocation(MethodInvocationTree tree, VisitorState state)59 public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) { 60 if (MISSING_LOCALE_ROOT.matches(tree, state)) { 61 return buildDescription(tree) 62 .setMessage("All case-altering methods must declare Locale.ROOT") 63 .build(); 64 } 65 return Description.NO_MATCH; 66 } 67 } 68