com.google.errorprone.bugpatterns.MutableConstantField Maven / Gradle / Ivy
/*
* Copyright 2017 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.bugpatterns;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.matchers.ChildMultiMatcher.MatchType.AT_LEAST_ONE;
import static com.google.errorprone.matchers.Matchers.annotations;
import static com.google.errorprone.matchers.Matchers.isSameType;
import com.google.common.base.Ascii;
import com.google.errorprone.BugPattern;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker.VariableTreeMatcher;
import com.google.errorprone.fixes.SuggestedFix;
import com.google.errorprone.fixes.SuggestedFixes;
import com.google.errorprone.matchers.Description;
import com.google.errorprone.matchers.MultiMatcher;
import com.google.errorprone.matchers.MultiMatcher.MultiMatchResult;
import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.VariableTree;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.Modifier;
/** @author [email protected] (Dori Reuveni) */
@BugPattern(
name = "MutableConstantField",
summary =
"Constant field declarations should use the immutable type (such as ImmutableList) instead"
+ " of the general collection interface type (such as List)",
severity = WARNING)
public final class MutableConstantField extends BugChecker implements VariableTreeMatcher {
private static final String BIND = "com.google.inject.testing.fieldbinder.Bind";
private static final MultiMatcher VAR_TO_BIND_ANNOTATION =
annotations(AT_LEAST_ONE, isSameType(BIND));
@Override
public Description matchVariable(VariableTree tree, VisitorState state) {
if (!isConstantField(ASTHelpers.getSymbol(tree))) {
return Description.NO_MATCH;
}
Tree rhsTree = tree.getInitializer();
Type rhsType = ASTHelpers.getType(rhsTree);
if (rhsType == null || !ImmutableCollections.isImmutableType(rhsType)) {
return Description.NO_MATCH;
}
Tree lhsTree = tree.getType();
Type lhsType = ASTHelpers.getType(lhsTree);
if (lhsType == null || ImmutableCollections.isImmutableType(lhsType)) {
return Description.NO_MATCH;
}
MultiMatchResult hasBindAnnotations =
VAR_TO_BIND_ANNOTATION.multiMatchResult(tree, state);
if (hasBindAnnotations.matches()) {
return Description.NO_MATCH;
}
String lhsTypeQualifiedName = getTypeQualifiedName(lhsType);
String newLhsTypeQualifiedName =
ImmutableCollections.mutableToImmutable(lhsTypeQualifiedName)
.orElse(getTypeQualifiedName(rhsType));
Type newLhsType = state.getTypeFromString(newLhsTypeQualifiedName);
SuggestedFix.Builder fixBuilder = SuggestedFix.builder();
fixBuilder.replace(
ASTHelpers.getErasedTypeTree(lhsTree),
SuggestedFixes.qualifyType(state, fixBuilder, newLhsType.asElement()));
SuggestedFix fix = fixBuilder.build();
return describeMatch(lhsTree, fix);
}
private static String getTypeQualifiedName(Type type) {
return type.tsym.getQualifiedName().toString();
}
private static boolean isConstantField(Symbol sym) {
return sym.getKind() == ElementKind.FIELD
&& isStaticFinalField(sym)
&& isConstantFieldName(sym.getSimpleName().toString());
}
private static boolean isStaticFinalField(Symbol sym) {
return sym.isStatic() && sym.getModifiers().contains(Modifier.FINAL);
}
private static boolean isConstantFieldName(String fieldName) {
return Ascii.toUpperCase(fieldName).equals(fieldName);
}
}