All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.checkerframework.checker.initialization.InitializationChecker Maven / Gradle / Ivy

Go to download

The Checker Framework enhances Java's type system to make it more powerful and useful. This lets software developers detect and prevent errors in their Java programs. The Checker Framework includes compiler plug-ins ("checkers") that find bugs or verify their absence. It also permits you to write your own compiler plug-ins.

There is a newer version: 3.42.0-eisop4
Show newest version
package org.checkerframework.checker.initialization;

import com.sun.source.tree.ClassTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.VariableTree;

import org.checkerframework.checker.initialization.qual.HoldsForDefaultValue;
import org.checkerframework.checker.initialization.qual.Initialized;
import org.checkerframework.checker.nullness.NullnessChecker;
import org.checkerframework.checker.nullness.NullnessNoInitAnnotatedTypeFactory;
import org.checkerframework.checker.nullness.NullnessNoInitSubchecker;
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.common.basetype.BaseTypeChecker;

import java.util.ArrayList;
import java.util.List;
import java.util.NavigableSet;
import java.util.Set;

/**
 * Tracks whether a value is initialized (all its fields are set), and checks that values are
 * initialized before being used. Implements the freedom-before-commitment scheme for
 * initialization, augmented by type frames.
 *
 * 

Because there is a cyclic dependency between this type system and the target type system, * using this checker is more complex than for others. Specifically: * *

    *
  1. Any target type system must provide two checkers: the target checker does all of the * checking of the target type system (e.g., nullness), while the target checker's parent * belongs to a subclass of the {@code InitializationChecker}. You can look at the {@link * NullnessChecker} for an example: For the nullness type system, the {@link * NullnessNoInitSubchecker} is the target checker which actually checks {@link NonNull} and * related qualifiers, while the {@link NullnessChecker} is a subclass of this checker and * thus checks {@link Initialized} and related qualifiers. The parent-child relationship * between the checkers is necessary because this checker is dependent on the target checker * to know which fields should be checked for initialization, and when such a field is * initialized: A field is checked for initialization if its declared type is not the top type * and does not have the meta-annotation {@link HoldsForDefaultValue} (e.g., {@link NonNull}). * Such a field becomes initialized as soon as its refined type agrees with its declared type * (which can happen either by assigning the field or by a contract annotation like {@link * EnsuresNonNull}). *
  2. The target checker must add the {@link InitializationFieldAccessSubchecker} as a subchecker * and the {@link InitializationFieldAccessTreeAnnotator} as a tree annotator. This is * necessary to give possibly uninitialized fields the top type of the target hierarchy (e.g., * {@link Nullable}), ensuring that all fields are initialized before being used. This needs * to be a separate checker because the target checker cannot access any type information from * its parent, which is only initialized after all subcheckers have finished. *
  3. The target checker must override all necessary methods in the target checker's type factory * to take the type information from the InitializationFieldAccessSubchecker into account. You * can look at {@link NullnessNoInitAnnotatedTypeFactory} for examples. *
  4. Any subclass of the {@code InitializationChecker} should support the command-line option * {@code -AassumeInitialized} via {@code @SupportedOptions({"assumeInitialized"})}, so * initialization checking can be turned off. This gives users of, e.g., the {@link * NullnessChecker} an easy way to turn off initialization checking without having to directly * call the {@link NullnessNoInitSubchecker}. *
* *

If you want to modify the freedom-before-commitment scheme in your subclass, note that the * InitializationChecker does not use the default convention where, e.g., the annotated type factory * for {@code NameChecker} is {@code NameAnnotatedTypeFactory}. Instead every subclass of this * checker always uses the {@link InitializationAnnotatedTypeFactory} unless this behavior is * overridden. Note also that the flow-sensitive type refinement for this type system is performed * by the {@link InitializationFieldAccessSubchecker}; this checker performs no refinement, instead * reusing the results from that one. * * @checker_framework.manual #initialization-checker Initialization Checker */ public abstract class InitializationChecker extends BaseTypeChecker { /** Default constructor for InitializationChecker. */ public InitializationChecker() {} /** * Whether to check primitives for initialization. * * @return whether to check primitives for initialization */ public abstract boolean checkPrimitives(); /** * The checker for the target type system for which to check initialization. * * @return the checker for the target type system. */ public abstract Class getTargetCheckerClass(); @Override public NavigableSet getSuppressWarningsPrefixes() { NavigableSet result = super.getSuppressWarningsPrefixes(); // "fbc" is for backward compatibility only; you should use // "initialization" instead. result.add("fbc"); // The default prefix "initialization" must be added manually because this checker class // is abstract and its subclasses are not named "InitializationChecker". result.add("initialization"); return result; } @Override protected Set> getImmediateSubcheckerClasses() { Set> checkers = super.getImmediateSubcheckerClasses(); checkers.add(getTargetCheckerClass()); return checkers; } /** * Returns a list of all fields of the given class. * * @param clazz the class * @return a list of all fields of {@code clazz} */ public static List getAllFields(ClassTree clazz) { List fields = new ArrayList<>(); for (Tree t : clazz.getMembers()) { if (t.getKind() == Tree.Kind.VARIABLE) { VariableTree vt = (VariableTree) t; fields.add(vt); } } return fields; } @Override public InitializationAnnotatedTypeFactory getTypeFactory() { return (InitializationAnnotatedTypeFactory) super.getTypeFactory(); } @Override protected InitializationVisitor createSourceVisitor() { return new InitializationVisitor(this); } @Override protected boolean messageKeyMatches( String messageKey, String messageKeyInSuppressWarningsString) { // Also support the shorter keys used by typetools return super.messageKeyMatches(messageKey, messageKeyInSuppressWarningsString) || super.messageKeyMatches( messageKey.replace(".invalid", ""), messageKeyInSuppressWarningsString); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy