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

framework.src.org.checkerframework.common.reflection.ClassValVisitor 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
Show newest version
package org.checkerframework.common.reflection;

import static org.checkerframework.common.reflection.ClassValAnnotatedTypeFactory.getClassNamesFromAnnotation;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.lang.model.element.AnnotationMirror;

import org.checkerframework.common.basetype.BaseTypeChecker;
import org.checkerframework.common.basetype.BaseTypeValidator;
import org.checkerframework.common.basetype.BaseTypeVisitor;
import org.checkerframework.common.reflection.qual.ClassBound;
import org.checkerframework.common.reflection.qual.ClassVal;
import org.checkerframework.framework.source.Result;
import org.checkerframework.framework.type.AnnotatedTypeFactory;
import org.checkerframework.framework.type.AnnotatedTypeMirror;

import com.sun.source.tree.Tree;

public class ClassValVisitor extends BaseTypeVisitor {
    public ClassValVisitor(BaseTypeChecker checker) {
        super(checker);
    }

    @Override
    protected ClassValAnnotatedTypeFactory createTypeFactory() {
        return new ClassValAnnotatedTypeFactory(checker);
    }
    @Override
    protected BaseTypeValidator createTypeValidator() {
        return new ClassNameValidator(checker, this, atypeFactory);
    }

}
class ClassNameValidator extends BaseTypeValidator {

    public ClassNameValidator(BaseTypeChecker checker,
            BaseTypeVisitor visitor, AnnotatedTypeFactory atypeFactory) {
        super(checker, visitor, atypeFactory);
    }

    /**
     * Reports an "illegal.classname" error if the type contains a classVal
     * annotation with classNames that cannot possibly be valid class
     * annotations.
     */
    @Override
    public boolean isValid(AnnotatedTypeMirror type, Tree tree) {
        AnnotationMirror classVal = type.getAnnotation(ClassVal.class);
        classVal = classVal == null ? type.getAnnotation(ClassBound.class)
                : classVal;
        if (classVal != null) {
            List classNames = getClassNamesFromAnnotation(classVal);
            for (String className : classNames) {
                if (!isLegalClassName(className)) {
                    checker.report(
                            Result.failure("illegal.classname", className, type), tree);
                }
            }
        }
        return super.isValid(type, tree);
    }

    /**
     * A string is a legal binary name if it has the following form:
     * ((Java identifier)\.)*(Java identifier)([])*
     * https://docs.oracle.com/javase/specs/jls/se8/html/jls-13.html#jls-13.1
     * @param className string to check
     * @return true if className is a legal class name
     */
    private boolean isLegalClassName(String className) {
        String regex = "([^\\.\\[\\]](\\.[^\\.\\[\\]])*)*(\\[\\])*";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(className);
        if (!m.matches()) {
            return false;
        }
        className = m.group(1);
        String[] identifiers = className.split(".");
        for (String identifier : identifiers) {
            if (!isJavaIdentifier(identifier)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Whether the given string is a Java Identifier. (This method returns true
     * if the Identifier is a keyword, boolean literal, null literal.
     */
    private boolean isJavaIdentifier(String identifier) {
        char[] identifierChars = identifier.toCharArray();
        if (!(identifierChars.length > 0 && (Character
                .isJavaIdentifierStart(identifierChars[0])))) {
            return false;
        }
        for (int i = 1; i < identifierChars.length; i++) {
            if (!Character.isJavaIdentifierPart(identifierChars[i])) {
                return false;
            }
        }
        return true;
    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy