CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-checkerframework--checker-qual

Type qualifier annotations for the Checker Framework static analysis tool

Pending
Overview
Eval results
Files

string-format.mddocs/

String and Format Annotations

String and format annotations validate string formats, regular expressions, and format strings to prevent runtime errors from malformed strings, invalid regex patterns, and mismatched format arguments.

Capabilities

Regular Expression Annotations

Annotations for validating regular expression patterns.

/**
 * Indicates that the annotated String is a valid regular expression
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf(UnknownRegex.class)
public @interface Regex {}

/**
 * Indicates a partial regular expression (part of a larger pattern)
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf(Regex.class)
public @interface PartialRegex {}

@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf({})
@DefaultQualifierInHierarchy
public @interface UnknownRegex {}

@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf(Regex.class)
public @interface RegexBottom {}

@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@PolymorphicQualifier(UnknownRegex.class)
public @interface PolyRegex {}

Usage Examples:

import org.checkerframework.checker.regex.qual.*;
import java.util.regex.Pattern;

public class RegexExample {
    // Method requires a valid regex pattern
    public Pattern compile(@Regex String pattern) {
        return Pattern.compile(pattern); // Safe - pattern is validated
    }
    
    // Method that validates and returns regex
    public @Regex String createEmailPattern() {
        return "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}";
    }
    
    // Polymorphic method preserves regex properties
    public @PolyRegex String process(@PolyRegex String input) {
        return input.trim();
    }
    
    public void example() {
        @Regex String emailRegex = createEmailPattern();
        Pattern emailPattern = compile(emailRegex); // Safe
        
        String userInput = getUserInput(); // Unknown if valid regex
        // compile(userInput); // Would cause type error
        
        if (isValidRegex(userInput)) {
            @Regex String validPattern = (@Regex String) userInput;
            Pattern pattern = compile(validPattern); // Safe after validation
        }
    }
    
    private boolean isValidRegex(String pattern) {
        try {
            Pattern.compile(pattern);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

Format String Annotations

Annotations for validating printf-style format strings and their arguments.

/**
 * Indicates a valid format string with specified conversion categories
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf(UnknownFormat.class)
public @interface Format {
    ConversionCategory[] value();
}

/**
 * Indicates an invalid format string
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf(UnknownFormat.class)
public @interface InvalidFormat {}

@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf({})
@DefaultQualifierInHierarchy
public @interface UnknownFormat {}

@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf(Format.class)
public @interface FormatBottom {}

/**
 * Method that returns a format string
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ReturnsFormat {}

/**
 * Method that uses format strings (like printf)
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FormatMethod {}

/**
 * Categories of printf conversion specifiers
 */
public enum ConversionCategory {
    UNUSED,      // %% - literal %
    GENERAL,     // %s, %b, %h - any type
    CHAR,        // %c - char, Character, byte, Byte, short, Short, int, Integer
    INT,         // %d, %o, %x - integral types
    FLOAT,       // %e, %f, %g - floating point types
    TIME,        // %t - date/time types
    CHAR_AND_INT, // %c or %d
    INT_AND_TIME  // %d or %t
}

Usage Examples:

import org.checkerframework.checker.formatter.qual.*;

public class FormatExample {
    // Method that requires a format string with specific argument types
    @FormatMethod
    public void logMessage(@Format({ConversionCategory.GENERAL, ConversionCategory.INT}) String format, 
                          Object message, int count) {
        System.out.printf(format, message, count); // Safe - format matches arguments
    }
    
    @ReturnsFormat({ConversionCategory.GENERAL, ConversionCategory.FLOAT})
    public String createFormatString() {
        return "User: %s, Score: %.2f";
    }
    
    public void example() {
        // Valid format strings
        @Format({ConversionCategory.GENERAL}) String nameFormat = "Hello, %s!";
        @Format({ConversionCategory.INT, ConversionCategory.FLOAT}) String scoreFormat = "Score: %d/%.1f";
        
        // Safe usage
        System.out.printf(nameFormat, "Alice");
        System.out.printf(scoreFormat, 85, 100.0);
        
        // Using method-created format
        @Format({ConversionCategory.GENERAL, ConversionCategory.FLOAT}) String userFormat = createFormatString();
        System.out.printf(userFormat, "Bob", 92.5);
        
        // Log with specific format requirements
        logMessage("Processing %s: %d items", "data.txt", 150);
    }
    
    // Method that validates and converts unknown format strings
    public @Format({ConversionCategory.GENERAL}) String validateSimpleFormat(String input) {
        if (input.matches("^[^%]*%s[^%]*$")) {
            return (@Format({ConversionCategory.GENERAL}) String) input;
        }
        throw new IllegalArgumentException("Invalid format string");
    }
}

Signature String Annotations

Annotations for Java signature strings used in reflection and bytecode operations.

/**
 * Java binary name (e.g., "java.lang.Object", "java.lang.Object$Inner")
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf(SignatureUnknown.class)
public @interface BinaryName {}

/**
 * Java canonical name (e.g., "java.lang.Object", "java.lang.Object.Inner")
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf(SignatureUnknown.class)
public @interface CanonicalName {}

/**
 * JVM field descriptor (e.g., "I", "Ljava/lang/String;")
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf(SignatureUnknown.class)
public @interface FieldDescriptor {}

/**
 * JVM method descriptor (e.g., "(I)V", "(Ljava/lang/String;)I")
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf(SignatureUnknown.class)
public @interface MethodDescriptor {}

/**
 * Java identifier (valid Java name)
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf(SignatureUnknown.class)
public @interface Identifier {}

@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@DefaultQualifierInHierarchy
public @interface SignatureUnknown {}

@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf(BinaryName.class)
public @interface SignatureBottom {}

@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@PolymorphicQualifier(SignatureUnknown.class)
public @interface PolySignature {}

Usage Examples:

import org.checkerframework.checker.signature.qual.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class SignatureExample {
    // Method that requires a valid Java binary name
    public Class<?> loadClass(@BinaryName String className) throws ClassNotFoundException {
        return Class.forName(className); // Safe - className is valid binary name
    }
    
    // Method that requires a field descriptor
    public void analyzeField(@FieldDescriptor String descriptor) {
        // Parse JVM field descriptor safely
        char typeChar = descriptor.charAt(0);
        switch (typeChar) {
            case 'I': System.out.println("int field"); break;
            case 'L': System.out.println("object field"); break;
            // ... other cases
        }
    }
    
    // Convert canonical name to binary name
    public @BinaryName String canonicalToBinary(@CanonicalName String canonical) {
        return canonical.replace('.', '$'); // Convert inner class separator
    }
    
    public void reflectionExample() throws Exception {
        // Valid binary names
        @BinaryName String stringClass = "java.lang.String";
        @BinaryName String innerClass = "java.util.Map$Entry";
        
        Class<?> clazz1 = loadClass(stringClass); // Safe
        Class<?> clazz2 = loadClass(innerClass);  // Safe
        
        // Field descriptors
        @FieldDescriptor String intDescriptor = "I";
        @FieldDescriptor String stringDescriptor = "Ljava/lang/String;";
        
        analyzeField(intDescriptor);    // Safe
        analyzeField(stringDescriptor); // Safe
        
        // Method descriptors for reflection
        @MethodDescriptor String voidMethod = "()V";
        @MethodDescriptor String stringToInt = "(Ljava/lang/String;)I";
        
        // Use in reflection calls (conceptual)
        // Method method = getMethodByDescriptor(clazz1, stringToInt);
    }
    
    // Validate Java identifier
    public boolean isValidIdentifier(@Identifier String name) {
        return Character.isJavaIdentifierStart(name.charAt(0)) &&
               name.chars().skip(1).allMatch(Character::isJavaIdentifierPart);
    }
}

Internationalization Format Annotations

Annotations for internationalized format strings and message keys.

/**
 * Valid internationalized format string
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf(I18nUnknownFormat.class)
public @interface I18nFormat {
    I18nConversionCategory[] value();
}

/**
 * Invalid internationalized format string
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf(I18nUnknownFormat.class)
public @interface I18nInvalidFormat {}

@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@DefaultQualifierInHierarchy
public @interface I18nUnknownFormat {}

/**
 * I18n conversion categories (similar to printf categories)
 */
public enum I18nConversionCategory {
    UNUSED,
    GENERAL,
    DATE,
    NUMBER
}

/**
 * Valid localizable key for resource bundles
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf(UnknownLocalizableKey.class)
public @interface LocalizableKey {}

@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@DefaultQualifierInHierarchy
public @interface UnknownLocalizableKey {}

/**
 * String that has been localized
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf(UnknownLocalized.class)
public @interface Localized {}

@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@DefaultQualifierInHierarchy
public @interface UnknownLocalized {}

Usage Examples:

import org.checkerframework.checker.i18n.qual.*;
import org.checkerframework.checker.i18nformatter.qual.*;
import java.util.ResourceBundle;
import java.text.MessageFormat;

public class I18nExample {
    private ResourceBundle bundle = ResourceBundle.getBundle("messages");
    
    // Method that requires a valid localizable key
    public @Localized String getMessage(@LocalizableKey String key) {
        return bundle.getString(key); // Safe - key is valid
    }
    
    // Method that formats i18n messages
    public @Localized String formatMessage(@I18nFormat({I18nConversionCategory.GENERAL, I18nConversionCategory.NUMBER}) String pattern,
                                          Object name, Number count) {
        return MessageFormat.format(pattern, name, count); // Safe - format matches arguments
    }
    
    public void example() {
        // Valid localizable keys (would be validated against resource bundle)
        @LocalizableKey String welcomeKey = "welcome.message";
        @LocalizableKey String errorKey = "error.file_not_found";
        
        // Get localized strings
        @Localized String welcome = getMessage(welcomeKey);
        @Localized String error = getMessage(errorKey);
        
        // Valid i18n format strings
        @I18nFormat({I18nConversionCategory.GENERAL}) String nameFormat = "Hello, {0}!";
        @I18nFormat({I18nConversionCategory.GENERAL, I18nConversionCategory.NUMBER}) 
        String countFormat = "Processing {0}: {1} items";
        
        // Safe formatting
        @Localized String greeting = formatMessage(nameFormat, "Alice");
        @Localized String status = formatMessage(countFormat, "data.txt", 150);
        
        System.out.println(greeting);
        System.out.println(status);
    }
}

Property Key Annotations

Annotations for validating property keys in configuration files.

/**
 * Valid property key for configuration files
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf(UnknownPropertyKey.class)
public @interface PropertyKey {}

@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@DefaultQualifierInHierarchy
public @interface UnknownPropertyKey {}

@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf(PropertyKey.class)
public @interface PropertyKeyBottom {}

Usage Examples:

import org.checkerframework.checker.propkey.qual.*;
import java.util.Properties;

public class PropertyExample {
    private Properties config = new Properties();
    
    // Method that requires a valid property key
    public String getProperty(@PropertyKey String key) {
        return config.getProperty(key); // Safe - key is validated
    }
    
    public void configure() {
        // Valid property keys (would be validated against properties file)
        @PropertyKey String dbUrlKey = "database.url";
        @PropertyKey String dbUserKey = "database.username";
        @PropertyKey String dbPassKey = "database.password";
        
        // Safe property access
        String dbUrl = getProperty(dbUrlKey);
        String dbUser = getProperty(dbUserKey);
        String dbPass = getProperty(dbPassKey);
        
        // Use configuration values
        connectToDatabase(dbUrl, dbUser, dbPass);
    }
    
    private void connectToDatabase(String url, String user, String password) {
        // Database connection logic
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-checkerframework--checker-qual

docs

concurrency.md

constant-value.md

contracts.md

framework.md

index-bounds.md

index.md

nullness.md

optional.md

resources.md

signedness.md

string-format.md

units.md

tile.json