package checkers.propkey; import java.lang.annotation.Annotation; import java.util.Set; import com.sun.source.tree.CompilationUnitTree; import com.sun.source.tree.LiteralTree; import com.sun.source.tree.Tree; import checkers.basetype.BaseTypeChecker; import checkers.propkey.quals.PropertyKey; import checkers.types.AnnotatedTypeFactory; import checkers.types.AnnotatedTypeMirror; import checkers.types.BasicAnnotatedTypeFactory; import checkers.types.TreeAnnotator; /** * This AnnotatedTypeFactory adds PropertyKey annotations to String literals * that contain values from lookupKeys. * * @author wmdietl */ public class PropertyKeyAnnotatedTypeFactory<Checker extends PropertyKeyChecker> extends BasicAnnotatedTypeFactory<Checker> { private final Set<String> lookupKeys; public PropertyKeyAnnotatedTypeFactory(Checker checker, CompilationUnitTree root) { super(checker, root); this.lookupKeys = checker.getLookupKeys(); } @Override public TreeAnnotator createTreeAnnotator(Checker checker) { return new KeyLookupTreeAnnotator(checker, this, PropertyKey.class); } /** * This TreeAnnotator checks for every String literal whether it is included in the lookup * keys. If it is, the given annotation is added to the literal; otherwise, nothing happens. * Subclasses of this AnnotatedTypeFactory can directly reuse this class and use a different * annotation as parameter. */ protected class KeyLookupTreeAnnotator extends TreeAnnotator { Class<? extends Annotation> theAnnot; public KeyLookupTreeAnnotator(BaseTypeChecker checker, AnnotatedTypeFactory tf, Class<? extends Annotation> annot) { super(checker, tf); theAnnot = annot; } @Override public Void visitLiteral(LiteralTree tree, AnnotatedTypeMirror type) { if (!type.isAnnotated() && tree.getKind() == Tree.Kind.STRING_LITERAL && lookupKeys.contains((String)tree.getValue())) { type.addAnnotation(theAnnot); } // A possible extension is to record all the keys that have been used and // in the end output a list of keys that were not used in the program, // possibly pointing to the opposite problem, keys that were supposed to // be used somewhere, but have not been, maybe because of copy-and-paste errors. return super.visitLiteral(tree, type); } } }