Loading errorprone/Android.bp 0 → 100644 +25 −0 Original line number Diff line number Diff line java_plugin { name: "error_prone_android_framework", static_libs: [ "error_prone_android_framework_lib", ], } java_library_host { name: "error_prone_android_framework_lib", srcs: ["java/**/*.java"], static_libs: [ "//external/error_prone:error_prone_core", "//external/dagger2:dagger2-auto-service", ], plugins: [ "//external/dagger2:dagger2-auto-service", ], javacflags: ["-verbose"], } errorprone/java/com/google/errorprone/bugpatterns/android/TargetSdkChecker.java 0 → 100644 +81 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * 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.google.errorprone.bugpatterns.android; import static com.google.errorprone.BugPattern.SeverityLevel.WARNING; import static com.google.errorprone.matchers.Matchers.allOf; import static com.google.errorprone.matchers.Matchers.anyOf; import static com.google.errorprone.matchers.Matchers.anything; import static com.google.errorprone.matchers.Matchers.kindIs; import com.google.auto.service.AutoService; import com.google.errorprone.BugPattern; import com.google.errorprone.VisitorState; import com.google.errorprone.bugpatterns.BugChecker; import com.google.errorprone.bugpatterns.BugChecker.BinaryTreeMatcher; import com.google.errorprone.matchers.Description; import com.google.errorprone.matchers.FieldMatchers; import com.google.errorprone.matchers.Matcher; import com.sun.source.tree.BinaryTree; import com.sun.source.tree.ExpressionTree; import com.sun.source.tree.Tree.Kind; @AutoService(BugChecker.class) @BugPattern( name = "AndroidFrameworkTargetSdk", summary = "Verifies that all target SDK comparisons are sane", severity = WARNING) public final class TargetSdkChecker extends BugChecker implements BinaryTreeMatcher { private static final Matcher<ExpressionTree> VERSION_CODE = FieldMatchers .anyFieldInClass("android.os.Build.VERSION_CODES"); private static final Matcher<BinaryTree> INVALID_OLD_BEHAVIOR = anyOf( allOf(kindIs(Kind.LESS_THAN_EQUAL), binaryTreeExact(anything(), VERSION_CODE)), allOf(kindIs(Kind.GREATER_THAN_EQUAL), binaryTreeExact(VERSION_CODE, anything()))); private static final Matcher<BinaryTree> INVALID_NEW_BEHAVIOR = anyOf( allOf(kindIs(Kind.GREATER_THAN), binaryTreeExact(anything(), VERSION_CODE)), allOf(kindIs(Kind.LESS_THAN), binaryTreeExact(VERSION_CODE, anything()))); @Override public Description matchBinary(BinaryTree tree, VisitorState state) { if (INVALID_OLD_BEHAVIOR.matches(tree, state)) { return buildDescription(tree) .setMessage("Legacy behaviors must be written in style " + "'targetSdk < Build.VERSION_CODES.Z'") .build(); } if (INVALID_NEW_BEHAVIOR.matches(tree, state)) { return buildDescription(tree) .setMessage("Modern behaviors must be written in style " + "'targetSdk >= Build.VERSION_CODES.Z'") .build(); } return Description.NO_MATCH; } private static Matcher<BinaryTree> binaryTreeExact(Matcher<ExpressionTree> left, Matcher<ExpressionTree> right) { return new Matcher<BinaryTree>() { @Override public boolean matches(BinaryTree tree, VisitorState state) { return left.matches(tree.getLeftOperand(), state) && right.matches(tree.getRightOperand(), state); } }; } } errorprone/java/com/google/errorprone/matchers/FieldMatchers.java 0 → 100644 +99 −0 Original line number Diff line number Diff line /* * Copyright 2018 The Error Prone Authors. * * 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.google.errorprone.matchers; import com.google.errorprone.VisitorState; import com.google.errorprone.util.ASTHelpers; import com.sun.source.tree.ExpressionTree; import com.sun.source.tree.ImportTree; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.ClassSymbol; import javax.annotation.Nullable; // TODO(glorioso): this likely wants to be a fluent interface like MethodMatchers. // Ex: [staticField()|instanceField()] // .[onClass(String)|onAnyClass|onClassMatching] // .[named(String)|withAnyName|withNameMatching] /** Static utility methods for creating {@link Matcher}s for detecting references to fields. */ public final class FieldMatchers { private FieldMatchers() {} public static Matcher<ExpressionTree> anyFieldInClass(String className) { return new FieldReferenceMatcher() { @Override boolean classIsAppropriate(ClassSymbol classSymbol) { return classSymbol.getQualifiedName().contentEquals(className); } @Override boolean fieldSymbolIsAppropriate(Symbol symbol) { return true; } }; } public static Matcher<ExpressionTree> staticField(String className, String fieldName) { return new FieldReferenceMatcher() { @Override boolean classIsAppropriate(ClassSymbol classSymbol) { return classSymbol.getQualifiedName().contentEquals(className); } @Override boolean fieldSymbolIsAppropriate(Symbol symbol) { return symbol.isStatic() && symbol.getSimpleName().contentEquals(fieldName); } }; } public static Matcher<ExpressionTree> instanceField(String className, String fieldName) { return new FieldReferenceMatcher() { @Override boolean classIsAppropriate(ClassSymbol classSymbol) { return classSymbol.getQualifiedName().contentEquals(className); } @Override boolean fieldSymbolIsAppropriate(Symbol symbol) { return !symbol.isStatic() && symbol.getSimpleName().contentEquals(fieldName); } }; } private abstract static class FieldReferenceMatcher implements Matcher<ExpressionTree> { @Override public boolean matches(ExpressionTree expressionTree, VisitorState state) { return isSymbolFieldInAppropriateClass(ASTHelpers.getSymbol(expressionTree)) // Don't match if this is part of a static import tree, since they will get the finding // on any usage of the field in their source. && ASTHelpers.findEnclosingNode(state.getPath(), ImportTree.class) == null; } private boolean isSymbolFieldInAppropriateClass(@Nullable Symbol symbol) { if (symbol == null) { return false; } return symbol.getKind().isField() && fieldSymbolIsAppropriate(symbol) && classIsAppropriate(symbol.owner.enclClass()); } abstract boolean fieldSymbolIsAppropriate(Symbol symbol); abstract boolean classIsAppropriate(ClassSymbol classSymbol); } } services/Android.bp +7 −1 Original line number Diff line number Diff line java_defaults { name: "services_defaults", plugins: [ "error_prone_android_framework", ], } filegroup { name: "services-main-sources", srcs: ["java/**/*.java"], Loading Loading @@ -83,7 +90,6 @@ java_library { // Uncomment to enable output of certain warnings (deprecated, unchecked) //javacflags: ["-Xlint"], } // native library Loading services/accessibility/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ filegroup { java_library_static { name: "services.accessibility", defaults: ["services_defaults"], srcs: [":services.accessibility-sources"], libs: ["services.core"], } Loading
errorprone/Android.bp 0 → 100644 +25 −0 Original line number Diff line number Diff line java_plugin { name: "error_prone_android_framework", static_libs: [ "error_prone_android_framework_lib", ], } java_library_host { name: "error_prone_android_framework_lib", srcs: ["java/**/*.java"], static_libs: [ "//external/error_prone:error_prone_core", "//external/dagger2:dagger2-auto-service", ], plugins: [ "//external/dagger2:dagger2-auto-service", ], javacflags: ["-verbose"], }
errorprone/java/com/google/errorprone/bugpatterns/android/TargetSdkChecker.java 0 → 100644 +81 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * 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.google.errorprone.bugpatterns.android; import static com.google.errorprone.BugPattern.SeverityLevel.WARNING; import static com.google.errorprone.matchers.Matchers.allOf; import static com.google.errorprone.matchers.Matchers.anyOf; import static com.google.errorprone.matchers.Matchers.anything; import static com.google.errorprone.matchers.Matchers.kindIs; import com.google.auto.service.AutoService; import com.google.errorprone.BugPattern; import com.google.errorprone.VisitorState; import com.google.errorprone.bugpatterns.BugChecker; import com.google.errorprone.bugpatterns.BugChecker.BinaryTreeMatcher; import com.google.errorprone.matchers.Description; import com.google.errorprone.matchers.FieldMatchers; import com.google.errorprone.matchers.Matcher; import com.sun.source.tree.BinaryTree; import com.sun.source.tree.ExpressionTree; import com.sun.source.tree.Tree.Kind; @AutoService(BugChecker.class) @BugPattern( name = "AndroidFrameworkTargetSdk", summary = "Verifies that all target SDK comparisons are sane", severity = WARNING) public final class TargetSdkChecker extends BugChecker implements BinaryTreeMatcher { private static final Matcher<ExpressionTree> VERSION_CODE = FieldMatchers .anyFieldInClass("android.os.Build.VERSION_CODES"); private static final Matcher<BinaryTree> INVALID_OLD_BEHAVIOR = anyOf( allOf(kindIs(Kind.LESS_THAN_EQUAL), binaryTreeExact(anything(), VERSION_CODE)), allOf(kindIs(Kind.GREATER_THAN_EQUAL), binaryTreeExact(VERSION_CODE, anything()))); private static final Matcher<BinaryTree> INVALID_NEW_BEHAVIOR = anyOf( allOf(kindIs(Kind.GREATER_THAN), binaryTreeExact(anything(), VERSION_CODE)), allOf(kindIs(Kind.LESS_THAN), binaryTreeExact(VERSION_CODE, anything()))); @Override public Description matchBinary(BinaryTree tree, VisitorState state) { if (INVALID_OLD_BEHAVIOR.matches(tree, state)) { return buildDescription(tree) .setMessage("Legacy behaviors must be written in style " + "'targetSdk < Build.VERSION_CODES.Z'") .build(); } if (INVALID_NEW_BEHAVIOR.matches(tree, state)) { return buildDescription(tree) .setMessage("Modern behaviors must be written in style " + "'targetSdk >= Build.VERSION_CODES.Z'") .build(); } return Description.NO_MATCH; } private static Matcher<BinaryTree> binaryTreeExact(Matcher<ExpressionTree> left, Matcher<ExpressionTree> right) { return new Matcher<BinaryTree>() { @Override public boolean matches(BinaryTree tree, VisitorState state) { return left.matches(tree.getLeftOperand(), state) && right.matches(tree.getRightOperand(), state); } }; } }
errorprone/java/com/google/errorprone/matchers/FieldMatchers.java 0 → 100644 +99 −0 Original line number Diff line number Diff line /* * Copyright 2018 The Error Prone Authors. * * 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.google.errorprone.matchers; import com.google.errorprone.VisitorState; import com.google.errorprone.util.ASTHelpers; import com.sun.source.tree.ExpressionTree; import com.sun.source.tree.ImportTree; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.ClassSymbol; import javax.annotation.Nullable; // TODO(glorioso): this likely wants to be a fluent interface like MethodMatchers. // Ex: [staticField()|instanceField()] // .[onClass(String)|onAnyClass|onClassMatching] // .[named(String)|withAnyName|withNameMatching] /** Static utility methods for creating {@link Matcher}s for detecting references to fields. */ public final class FieldMatchers { private FieldMatchers() {} public static Matcher<ExpressionTree> anyFieldInClass(String className) { return new FieldReferenceMatcher() { @Override boolean classIsAppropriate(ClassSymbol classSymbol) { return classSymbol.getQualifiedName().contentEquals(className); } @Override boolean fieldSymbolIsAppropriate(Symbol symbol) { return true; } }; } public static Matcher<ExpressionTree> staticField(String className, String fieldName) { return new FieldReferenceMatcher() { @Override boolean classIsAppropriate(ClassSymbol classSymbol) { return classSymbol.getQualifiedName().contentEquals(className); } @Override boolean fieldSymbolIsAppropriate(Symbol symbol) { return symbol.isStatic() && symbol.getSimpleName().contentEquals(fieldName); } }; } public static Matcher<ExpressionTree> instanceField(String className, String fieldName) { return new FieldReferenceMatcher() { @Override boolean classIsAppropriate(ClassSymbol classSymbol) { return classSymbol.getQualifiedName().contentEquals(className); } @Override boolean fieldSymbolIsAppropriate(Symbol symbol) { return !symbol.isStatic() && symbol.getSimpleName().contentEquals(fieldName); } }; } private abstract static class FieldReferenceMatcher implements Matcher<ExpressionTree> { @Override public boolean matches(ExpressionTree expressionTree, VisitorState state) { return isSymbolFieldInAppropriateClass(ASTHelpers.getSymbol(expressionTree)) // Don't match if this is part of a static import tree, since they will get the finding // on any usage of the field in their source. && ASTHelpers.findEnclosingNode(state.getPath(), ImportTree.class) == null; } private boolean isSymbolFieldInAppropriateClass(@Nullable Symbol symbol) { if (symbol == null) { return false; } return symbol.getKind().isField() && fieldSymbolIsAppropriate(symbol) && classIsAppropriate(symbol.owner.enclClass()); } abstract boolean fieldSymbolIsAppropriate(Symbol symbol); abstract boolean classIsAppropriate(ClassSymbol classSymbol); } }
services/Android.bp +7 −1 Original line number Diff line number Diff line java_defaults { name: "services_defaults", plugins: [ "error_prone_android_framework", ], } filegroup { name: "services-main-sources", srcs: ["java/**/*.java"], Loading Loading @@ -83,7 +90,6 @@ java_library { // Uncomment to enable output of certain warnings (deprecated, unchecked) //javacflags: ["-Xlint"], } // native library Loading
services/accessibility/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ filegroup { java_library_static { name: "services.accessibility", defaults: ["services_defaults"], srcs: [":services.accessibility-sources"], libs: ["services.core"], }