Search in sources :

Example 1 with RuleDependency

use of org.antlr.v4.runtime.RuleDependency in project antlr4 by tunnelvisionlabs.

the class RuleDependencyChecker method getElementDependencies.

private static void getElementDependencies(AnnotatedElement annotatedElement, List<Tuple2<RuleDependency, AnnotatedElement>> result) {
    RuleDependency dependency = annotatedElement.getAnnotation(RuleDependency.class);
    if (dependency != null) {
        result.add(Tuple.create(dependency, annotatedElement));
    }
    RuleDependencies dependencies = annotatedElement.getAnnotation(RuleDependencies.class);
    if (dependencies != null) {
        for (RuleDependency d : dependencies.value()) {
            if (d != null) {
                result.add(Tuple.create(d, annotatedElement));
            }
        }
    }
}
Also used : RuleDependencies(org.antlr.v4.runtime.RuleDependencies) RuleDependency(org.antlr.v4.runtime.RuleDependency)

Example 2 with RuleDependency

use of org.antlr.v4.runtime.RuleDependency in project antlr4 by tunnelvisionlabs.

the class RuleDependencyChecker method getDependencies.

public static List<Tuple2<RuleDependency, AnnotatedElement>> getDependencies(Class<?> clazz) {
    List<Tuple2<RuleDependency, AnnotatedElement>> result = new ArrayList<Tuple2<RuleDependency, AnnotatedElement>>();
    List<ElementType> supportedTarget = Arrays.asList(RuleDependency.class.getAnnotation(Target.class).value());
    for (ElementType target : supportedTarget) {
        switch(target) {
            case TYPE:
                if (!clazz.isAnnotation()) {
                    getElementDependencies(clazz, result);
                }
                break;
            case ANNOTATION_TYPE:
                if (!clazz.isAnnotation()) {
                    getElementDependencies(clazz, result);
                }
                break;
            case CONSTRUCTOR:
                for (Constructor<?> ctor : clazz.getDeclaredConstructors()) {
                    getElementDependencies(ctor, result);
                }
                break;
            case FIELD:
                for (Field field : clazz.getDeclaredFields()) {
                    getElementDependencies(field, result);
                }
                break;
            case LOCAL_VARIABLE:
                System.err.println("Runtime rule dependency checking is not supported for local variables.");
                break;
            case METHOD:
                for (Method method : clazz.getDeclaredMethods()) {
                    getElementDependencies(method, result);
                }
                break;
            case PACKAGE:
                // package is not a subset of class, so nothing to do here
                break;
            case PARAMETER:
                System.err.println("Runtime rule dependency checking is not supported for parameters.");
                break;
        }
    }
    return result;
}
Also used : Field(java.lang.reflect.Field) ElementType(java.lang.annotation.ElementType) ArrayList(java.util.ArrayList) AnnotatedElement(java.lang.reflect.AnnotatedElement) Method(java.lang.reflect.Method) RuleDependency(org.antlr.v4.runtime.RuleDependency)

Example 3 with RuleDependency

use of org.antlr.v4.runtime.RuleDependency in project antlr4 by tunnelvisionlabs.

the class RuleDependencyProcessor method checkDependencies.

private void checkDependencies(List<Tuple2<RuleDependency, Element>> dependencies, TypeMirror recognizerType) {
    String[] ruleNames = getRuleNames(recognizerType);
    int[] ruleVersions = getRuleVersions(recognizerType, ruleNames);
    RuleRelations relations = extractRuleRelations(recognizerType);
    for (Tuple2<RuleDependency, Element> dependency : dependencies) {
        try {
            if (!processingEnv.getTypeUtils().isAssignable(getRecognizerType(dependency.getItem1()), recognizerType)) {
                continue;
            }
            // this is the rule in the dependency set with the highest version number
            int effectiveRule = dependency.getItem1().rule();
            if (effectiveRule < 0 || effectiveRule >= ruleVersions.length) {
                Tuple2<AnnotationMirror, AnnotationValue> ruleReferenceElement = findRuleDependencyProperty(dependency, RuleDependencyProperty.RULE);
                String message = String.format("Rule dependency on unknown rule %d@%d in %s", dependency.getItem1().rule(), dependency.getItem1().version(), getRecognizerType(dependency.getItem1()).toString());
                if (ruleReferenceElement != null) {
                    processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, message, dependency.getItem2(), ruleReferenceElement.getItem1(), ruleReferenceElement.getItem2());
                } else {
                    processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, message, dependency.getItem2());
                }
                continue;
            }
            EnumSet<Dependents> dependents = EnumSet.of(Dependents.SELF, dependency.getItem1().dependents());
            reportUnimplementedDependents(dependency, dependents);
            BitSet checked = new BitSet();
            int highestRequiredDependency = checkDependencyVersion(dependency, ruleNames, ruleVersions, effectiveRule, null);
            if (dependents.contains(Dependents.PARENTS)) {
                BitSet parents = relations.parents[dependency.getItem1().rule()];
                for (int parent = parents.nextSetBit(0); parent >= 0; parent = parents.nextSetBit(parent + 1)) {
                    if (parent < 0 || parent >= ruleVersions.length || checked.get(parent)) {
                        continue;
                    }
                    checked.set(parent);
                    int required = checkDependencyVersion(dependency, ruleNames, ruleVersions, parent, "parent");
                    highestRequiredDependency = Math.max(highestRequiredDependency, required);
                }
            }
            if (dependents.contains(Dependents.CHILDREN)) {
                BitSet children = relations.children[dependency.getItem1().rule()];
                for (int child = children.nextSetBit(0); child >= 0; child = children.nextSetBit(child + 1)) {
                    if (child < 0 || child >= ruleVersions.length || checked.get(child)) {
                        continue;
                    }
                    checked.set(child);
                    int required = checkDependencyVersion(dependency, ruleNames, ruleVersions, child, "child");
                    highestRequiredDependency = Math.max(highestRequiredDependency, required);
                }
            }
            if (dependents.contains(Dependents.ANCESTORS)) {
                BitSet ancestors = relations.getAncestors(dependency.getItem1().rule());
                for (int ancestor = ancestors.nextSetBit(0); ancestor >= 0; ancestor = ancestors.nextSetBit(ancestor + 1)) {
                    if (ancestor < 0 || ancestor >= ruleVersions.length || checked.get(ancestor)) {
                        continue;
                    }
                    checked.set(ancestor);
                    int required = checkDependencyVersion(dependency, ruleNames, ruleVersions, ancestor, "ancestor");
                    highestRequiredDependency = Math.max(highestRequiredDependency, required);
                }
            }
            if (dependents.contains(Dependents.DESCENDANTS)) {
                BitSet descendants = relations.getDescendants(dependency.getItem1().rule());
                for (int descendant = descendants.nextSetBit(0); descendant >= 0; descendant = descendants.nextSetBit(descendant + 1)) {
                    if (descendant < 0 || descendant >= ruleVersions.length || checked.get(descendant)) {
                        continue;
                    }
                    checked.set(descendant);
                    int required = checkDependencyVersion(dependency, ruleNames, ruleVersions, descendant, "descendant");
                    highestRequiredDependency = Math.max(highestRequiredDependency, required);
                }
            }
            int declaredVersion = dependency.getItem1().version();
            if (declaredVersion > highestRequiredDependency) {
                Tuple2<AnnotationMirror, AnnotationValue> versionElement = findRuleDependencyProperty(dependency, RuleDependencyProperty.VERSION);
                String message = String.format("Rule dependency version mismatch: %s has maximum dependency version %d (expected %d) in %s", ruleNames[dependency.getItem1().rule()], highestRequiredDependency, declaredVersion, getRecognizerType(dependency.getItem1()).toString());
                if (versionElement != null) {
                    processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, message, dependency.getItem2(), versionElement.getItem1(), versionElement.getItem2());
                } else {
                    processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, message, dependency.getItem2());
                }
            }
        } catch (AnnotationTypeMismatchException ex) {
            processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, String.format("Could not validate rule dependencies for element %s", dependency.getItem2().toString()), dependency.getItem2());
        }
    }
}
Also used : VariableElement(javax.lang.model.element.VariableElement) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) BitSet(java.util.BitSet) AnnotationTypeMismatchException(java.lang.annotation.AnnotationTypeMismatchException) AnnotationMirror(javax.lang.model.element.AnnotationMirror) Dependents(org.antlr.v4.runtime.Dependents) AnnotationValue(javax.lang.model.element.AnnotationValue) RuleDependency(org.antlr.v4.runtime.RuleDependency)

Example 4 with RuleDependency

use of org.antlr.v4.runtime.RuleDependency in project antlr4 by tunnelvisionlabs.

the class RuleDependencyProcessor method process.

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    if (!checkClassNameConstants()) {
        return true;
    }
    List<Tuple2<RuleDependency, Element>> dependencies = getDependencies(roundEnv);
    Map<TypeMirror, List<Tuple2<RuleDependency, Element>>> recognizerDependencies = new HashMap<TypeMirror, List<Tuple2<RuleDependency, Element>>>();
    for (Tuple2<RuleDependency, Element> dependency : dependencies) {
        TypeMirror recognizerType = getRecognizerType(dependency.getItem1());
        List<Tuple2<RuleDependency, Element>> list = recognizerDependencies.get(recognizerType);
        if (list == null) {
            list = new ArrayList<Tuple2<RuleDependency, Element>>();
            recognizerDependencies.put(recognizerType, list);
        }
        list.add(dependency);
    }
    for (Map.Entry<TypeMirror, List<Tuple2<RuleDependency, Element>>> entry : recognizerDependencies.entrySet()) {
        processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, String.format("ANTLR 4: Validating %d dependencies on rules in %s.", entry.getValue().size(), entry.getKey().toString()));
        checkDependencies(entry.getValue(), entry.getKey());
    }
    return true;
}
Also used : TypeMirror(javax.lang.model.type.TypeMirror) HashMap(java.util.HashMap) VariableElement(javax.lang.model.element.VariableElement) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) ArrayList(java.util.ArrayList) List(java.util.List) HashMap(java.util.HashMap) Map(java.util.Map) RuleDependency(org.antlr.v4.runtime.RuleDependency)

Example 5 with RuleDependency

use of org.antlr.v4.runtime.RuleDependency in project antlr4 by tunnelvisionlabs.

the class RuleDependencyProcessor method getDependencies.

public static List<Tuple2<RuleDependency, Element>> getDependencies(RoundEnvironment roundEnv) {
    List<Tuple2<RuleDependency, Element>> result = new ArrayList<Tuple2<RuleDependency, Element>>();
    Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(RuleDependency.class);
    for (Element element : elements) {
        RuleDependency dependency = element.getAnnotation(RuleDependency.class);
        if (dependency == null) {
            continue;
        }
        result.add(Tuple.create(dependency, element));
    }
    elements = roundEnv.getElementsAnnotatedWith(RuleDependencies.class);
    for (Element element : elements) {
        RuleDependencies dependencies = element.getAnnotation(RuleDependencies.class);
        if (dependencies == null || dependencies.value() == null) {
            continue;
        }
        for (RuleDependency dependency : dependencies.value()) {
            result.add(Tuple.create(dependency, element));
        }
    }
    return result;
}
Also used : RuleDependencies(org.antlr.v4.runtime.RuleDependencies) VariableElement(javax.lang.model.element.VariableElement) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) ArrayList(java.util.ArrayList) RuleDependency(org.antlr.v4.runtime.RuleDependency)

Aggregations

RuleDependency (org.antlr.v4.runtime.RuleDependency)5 ArrayList (java.util.ArrayList)3 Element (javax.lang.model.element.Element)3 ExecutableElement (javax.lang.model.element.ExecutableElement)3 TypeElement (javax.lang.model.element.TypeElement)3 VariableElement (javax.lang.model.element.VariableElement)3 RuleDependencies (org.antlr.v4.runtime.RuleDependencies)2 AnnotationTypeMismatchException (java.lang.annotation.AnnotationTypeMismatchException)1 ElementType (java.lang.annotation.ElementType)1 AnnotatedElement (java.lang.reflect.AnnotatedElement)1 Field (java.lang.reflect.Field)1 Method (java.lang.reflect.Method)1 BitSet (java.util.BitSet)1 HashMap (java.util.HashMap)1 List (java.util.List)1 Map (java.util.Map)1 AnnotationMirror (javax.lang.model.element.AnnotationMirror)1 AnnotationValue (javax.lang.model.element.AnnotationValue)1 TypeMirror (javax.lang.model.type.TypeMirror)1 Dependents (org.antlr.v4.runtime.Dependents)1