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));
}
}
}
}
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;
}
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());
}
}
}
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;
}
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;
}
Aggregations