use of javax.lang.model.element.AnnotationMirror in project graal by oracle.
the class NodeParser method parseChildren.
private List<NodeChildData> parseChildren(NodeData node, final List<TypeElement> typeHierarchy, List<? extends Element> elements) {
Map<String, TypeMirror> castNodeTypes = new HashMap<>();
for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, CreateCast.class);
if (mirror != null) {
List<String> children = (ElementUtils.getAnnotationValueList(String.class, mirror, "value"));
if (children != null) {
for (String child : children) {
castNodeTypes.put(child, method.getReturnType());
}
}
}
}
List<NodeChildData> executedFieldChildren = new ArrayList<>();
for (VariableElement field : ElementFilter.fieldsIn(elements)) {
if (field.getModifiers().contains(Modifier.STATIC)) {
continue;
}
AnnotationMirror executed = ElementUtils.findAnnotationMirror(field.getAnnotationMirrors(), context.getDeclaredType(Executed.class));
if (executed != null) {
TypeMirror type = field.asType();
String name = field.getSimpleName().toString();
Cardinality cardinality = Cardinality.ONE;
if (type.getKind() == TypeKind.ARRAY) {
cardinality = Cardinality.MANY;
}
AnnotationValue executedWith = ElementUtils.getAnnotationValue(executed, "with");
NodeChildData child = new NodeChildData(field, executed, name, type, type, field, cardinality, executedWith);
executedFieldChildren.add(child);
if (field.getModifiers().contains(Modifier.PRIVATE)) {
child.addError("Field annotated with @%s must be visible for the generated subclass to execute.", Executed.class.getSimpleName());
}
if (cardinality == Cardinality.ONE) {
if (field.getAnnotation(Child.class) == null) {
child.addError("Field annotated with @%s must also be annotated with @%s.", Executed.class.getSimpleName(), Child.class.getSimpleName());
}
} else {
assert cardinality == Cardinality.MANY;
if (field.getAnnotation(Children.class) == null) {
child.addError("Field annotated with @%s must also be annotated with @%s.", Executed.class.getSimpleName(), Children.class.getSimpleName());
}
}
}
}
NodeChildData many = null;
Set<String> names = new HashSet<>();
for (NodeChildData child : executedFieldChildren) {
if (child.needsGeneratedField()) {
throw new AssertionError("Should not need generated field.");
}
if (names.contains(child.getName())) {
child.addError("Field annotated with @%s has duplicate name '%s'. " + "Executed children must have unique names.", Executed.class.getSimpleName(), child.getName());
} else if (many != null) {
child.addError("Field annotated with @%s is hidden by executed field '%s'. " + "Executed child fields with multiple children hide all following executed child declarations. " + "Reorder or remove this executed child declaration.", Executed.class.getSimpleName(), many.getName());
} else if (child.getCardinality().isMany()) {
many = child;
}
names.add(child.getName());
}
List<NodeChildData> nodeChildren = new ArrayList<>();
List<TypeElement> typeHierarchyReversed = new ArrayList<>(typeHierarchy);
Collections.reverse(typeHierarchyReversed);
for (TypeElement type : typeHierarchyReversed) {
AnnotationMirror nodeChildrenMirror = ElementUtils.findAnnotationMirror(processingEnv, type, NodeChildren.class);
TypeMirror nodeClassType = type.getSuperclass();
if (!ElementUtils.isAssignable(nodeClassType, context.getTruffleTypes().getNode())) {
nodeClassType = null;
}
List<AnnotationMirror> children = ElementUtils.collectAnnotations(context, nodeChildrenMirror, "value", type, NodeChild.class);
int index = 0;
for (AnnotationMirror childMirror : children) {
String name = ElementUtils.getAnnotationValue(String.class, childMirror, "value");
if (name.equals("")) {
name = "child" + index;
}
Cardinality cardinality = Cardinality.ONE;
TypeMirror childNodeType = inheritType(childMirror, "type", nodeClassType);
if (childNodeType.getKind() == TypeKind.ARRAY) {
cardinality = Cardinality.MANY;
}
TypeMirror originalChildType = childNodeType;
TypeMirror castNodeType = castNodeTypes.get(name);
if (castNodeType != null) {
childNodeType = castNodeType;
}
Element getter = findGetter(elements, name, childNodeType);
AnnotationValue executeWith = ElementUtils.getAnnotationValue(childMirror, "executeWith");
NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childNodeType, originalChildType, getter, cardinality, executeWith);
nodeChildren.add(nodeChild);
if (nodeChild.getNodeType() == null) {
nodeChild.addError("No valid node type could be resoleved.");
}
if (nodeChild.hasErrors()) {
continue;
}
index++;
}
}
if (!nodeChildren.isEmpty() && !executedFieldChildren.isEmpty()) {
node.addError("The use of @%s and @%s at the same time is not supported.", NodeChild.class.getSimpleName(), Executed.class.getSimpleName());
return executedFieldChildren;
} else if (!executedFieldChildren.isEmpty()) {
return executedFieldChildren;
} else {
List<NodeChildData> filteredChildren = new ArrayList<>();
Set<String> encounteredNames = new HashSet<>();
for (int i = nodeChildren.size() - 1; i >= 0; i--) {
NodeChildData child = nodeChildren.get(i);
if (!encounteredNames.contains(child.getName())) {
filteredChildren.add(0, child);
encounteredNames.add(child.getName());
}
}
return filteredChildren;
}
}
use of javax.lang.model.element.AnnotationMirror in project graal by oracle.
the class NodeParser method initializeCaches.
private void initializeCaches(SpecializationData specialization, DSLExpressionResolver resolver) {
TypeMirror cacheMirror = context.getType(Cached.class);
List<CacheExpression> expressions = new ArrayList<>();
for (Parameter parameter : specialization.getParameters()) {
AnnotationMirror annotationMirror = ElementUtils.findAnnotationMirror(parameter.getVariableElement().getAnnotationMirrors(), cacheMirror);
if (annotationMirror != null) {
String initializer = ElementUtils.getAnnotationValue(String.class, annotationMirror, "value");
TypeMirror parameterType = parameter.getType();
DSLExpressionResolver localResolver = resolver;
if (parameterType.getKind() == TypeKind.DECLARED) {
localResolver = localResolver.copy(importPublicStaticMembers(ElementUtils.fromTypeMirror(parameterType), true));
}
CacheExpression cacheExpression;
DSLExpression expression = null;
try {
expression = DSLExpression.parse(initializer);
expression.accept(localResolver);
cacheExpression = new CacheExpression(parameter, annotationMirror, expression);
if (!ElementUtils.typeEquals(expression.getResolvedType(), parameter.getType())) {
cacheExpression.addError("Incompatible return type %s. The expression type must be equal to the parameter type %s.", ElementUtils.getSimpleName(expression.getResolvedType()), ElementUtils.getSimpleName(parameter.getType()));
}
} catch (InvalidExpressionException e) {
cacheExpression = new CacheExpression(parameter, annotationMirror, null);
cacheExpression.addError("Error parsing expression '%s': %s", initializer, e.getMessage());
}
if (!cacheExpression.hasErrors()) {
Cached cached = cacheExpression.getParameter().getVariableElement().getAnnotation(Cached.class);
cacheExpression.setDimensions(cached.dimensions());
if (parameterType.getKind() == TypeKind.ARRAY && !ElementUtils.isSubtype(((ArrayType) parameterType).getComponentType(), context.getType(NodeInterface.class))) {
if (cacheExpression.getDimensions() == -1) {
cacheExpression.addWarning("The cached dimensions attribute must be specified for array types.");
}
} else {
if (cacheExpression.getDimensions() != -1) {
cacheExpression.addError("The dimensions attribute has no affect for the type %s.", ElementUtils.getSimpleName(parameterType));
}
}
}
expressions.add(cacheExpression);
}
}
specialization.setCaches(expressions);
if (specialization.hasErrors()) {
return;
}
// verify that cache expressions are bound in the correct order.
for (int i = 0; i < expressions.size(); i++) {
CacheExpression currentExpression = expressions.get(i);
Set<VariableElement> boundVariables = currentExpression.getExpression().findBoundVariableElements();
for (int j = i + 1; j < expressions.size(); j++) {
CacheExpression boundExpression = expressions.get(j);
if (boundVariables.contains(boundExpression.getParameter().getVariableElement())) {
currentExpression.addError("The initializer expression of parameter '%s' binds unitialized parameter '%s. Reorder the parameters to resolve the problem.", currentExpression.getParameter().getLocalName(), boundExpression.getParameter().getLocalName());
break;
}
}
}
}
use of javax.lang.model.element.AnnotationMirror in project graal by oracle.
the class NodeParser method parseExecutions.
private List<NodeExecutionData> parseExecutions(List<NodeFieldData> fields, List<NodeChildData> children, List<? extends Element> elements) {
List<ExecutableElement> methods = ElementFilter.methodsIn(elements);
boolean hasVarArgs = false;
int maxSignatureSize = 0;
if (!children.isEmpty()) {
int lastIndex = children.size() - 1;
hasVarArgs = children.get(lastIndex).getCardinality() == Cardinality.MANY;
if (hasVarArgs) {
maxSignatureSize = lastIndex;
} else {
maxSignatureSize = children.size();
}
}
List<NodeFieldData> nonGetterFields = new ArrayList<>();
for (NodeFieldData field : fields) {
if (field.getGetter() == null && field.isGenerated()) {
nonGetterFields.add(field);
}
}
TypeMirror cacheAnnotation = context.getType(Cached.class);
List<TypeMirror> frameTypes = context.getFrameTypes();
// pre-parse specializations to find signature size
for (ExecutableElement method : methods) {
AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, Specialization.class);
if (mirror == null) {
continue;
}
int currentArgumentIndex = 0;
parameter: for (VariableElement var : method.getParameters()) {
TypeMirror type = var.asType();
if (currentArgumentIndex == 0) {
// skip optionals
for (TypeMirror frameType : frameTypes) {
if (ElementUtils.typeEquals(type, frameType)) {
continue parameter;
}
}
}
if (currentArgumentIndex < nonGetterFields.size()) {
for (NodeFieldData field : nonGetterFields) {
if (ElementUtils.typeEquals(var.asType(), field.getType())) {
continue parameter;
}
}
}
if (ElementUtils.findAnnotationMirror(var.getAnnotationMirrors(), cacheAnnotation) != null) {
continue parameter;
}
currentArgumentIndex++;
}
maxSignatureSize = Math.max(maxSignatureSize, currentArgumentIndex);
}
List<NodeExecutionData> executions = new ArrayList<>();
for (int i = 0; i < maxSignatureSize; i++) {
boolean varArgParameter = false;
int childIndex = i;
if (i >= children.size() - 1) {
if (hasVarArgs) {
varArgParameter = hasVarArgs;
childIndex = Math.min(i, children.size() - 1);
} else if (i >= children.size()) {
childIndex = -1;
}
}
int varArgsIndex = -1;
NodeChildData child = null;
if (childIndex != -1) {
varArgsIndex = varArgParameter ? Math.abs(childIndex - i) : -1;
child = children.get(childIndex);
}
executions.add(new NodeExecutionData(child, i, varArgsIndex));
}
return executions;
}
use of javax.lang.model.element.AnnotationMirror in project graal by oracle.
the class AbstractParser method parse.
public final M parse(Element element) {
M model = null;
try {
AnnotationMirror mirror = null;
if (getAnnotationType() != null) {
mirror = ElementUtils.findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), getAnnotationType());
}
if (!context.getTruffleTypes().verify(context, element, mirror)) {
return null;
}
model = parse(element, mirror);
if (model == null) {
return null;
}
redirectMessages(new HashSet<MessageContainer>(), model, model);
model.emitMessages(context, log);
if (model instanceof NodeData) {
return model;
} else {
return filterErrorElements(model);
}
} catch (CompileErrorException e) {
log.message(Kind.WARNING, element, null, null, "The truffle processor could not parse class due to error: %s", e.getMessage());
return null;
}
}
use of javax.lang.model.element.AnnotationMirror in project graal by oracle.
the class CreateCastParser method create.
@Override
public CreateCastData create(TemplateMethod method, boolean invalid) {
AnnotationMirror mirror = method.getMarkerAnnotation();
List<String> childNames = ElementUtils.getAnnotationValueList(String.class, mirror, "value");
CreateCastData cast = new CreateCastData(method, childNames);
AnnotationValue value = ElementUtils.getAnnotationValue(mirror, "value");
TypeMirror type = null;
if (childNames == null || childNames.isEmpty()) {
cast.addError(value, "No value specified but required.");
return cast;
}
for (String childName : childNames) {
NodeChildData child = getNode().findChild(childName);
if (child == null) {
// error
cast.addError(value, "Specified child '%s' not found.", childName);
continue;
}
if (type == null) {
type = child.getNodeType();
} else if (!ElementUtils.typeEquals(type, child.getNodeType())) {
cast.addError(value, "All child nodes for a cast must have the same node type.");
continue;
}
}
return cast;
}
Aggregations