package com.oracle.truffle.dsl.processor.parser;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.tools.Diagnostic.Kind;
import com.oracle.truffle.dsl.processor.CompileErrorException;
import com.oracle.truffle.dsl.processor.Log;
import com.oracle.truffle.dsl.processor.ProcessorContext;
import com.oracle.truffle.dsl.processor.TruffleProcessorOptions;
import com.oracle.truffle.dsl.processor.TruffleTypes;
import com.oracle.truffle.dsl.processor.java.ElementUtils;
import com.oracle.truffle.dsl.processor.library.LibraryData;
import com.oracle.truffle.dsl.processor.model.MessageContainer;
import com.oracle.truffle.dsl.processor.model.NodeData;
public abstract class AbstractParser<M extends MessageContainer> {
protected final ProcessorContext context;
protected final ProcessingEnvironment processingEnv;
protected final TruffleTypes types = ProcessorContext.getInstance().getTypes();
protected boolean generateSlowPathOnly;
protected final String generateSlowPathOnlyFilter;
protected final Log log;
public AbstractParser() {
this.context = ProcessorContext.getInstance();
this.processingEnv = context.getEnvironment();
this.log = context.getLog();
this.generateSlowPathOnly = TruffleProcessorOptions.generateSlowPathOnly(processingEnv);
this.generateSlowPathOnlyFilter = TruffleProcessorOptions.generateSlowPathOnlyFilter(processingEnv);
}
protected void setGenerateSlowPathOnly(boolean flag) {
this.generateSlowPathOnly = flag;
}
protected boolean isGenerateSlowPathOnly(NodeData node) {
return isGenerateSlowPathOnly(node.getTemplateType());
}
protected boolean isGenerateSlowPathOnly(TypeElement element) {
if (types.AlwaysSlowPath != null && ElementUtils.findAnnotationMirror(element, types.AlwaysSlowPath) != null) {
return true;
}
if (!generateSlowPathOnly) {
return false;
}
if (generateSlowPathOnlyFilter != null) {
String nodeQName = element.getQualifiedName().toString();
return nodeQName.startsWith(generateSlowPathOnlyFilter);
}
return true;
}
public final M parse(Element element, boolean emitErrors) {
M model = null;
try {
List<AnnotationMirror> mirrors = null;
if (getAnnotationType() != null) {
mirrors = ElementUtils.getRepeatedAnnotation(element.getAnnotationMirrors(), getAnnotationType());
}
model = parse(element, mirrors);
if (model == null) {
return null;
}
if (emitErrors) {
model.emitMessages(context, log);
}
if (model instanceof NodeData || model instanceof LibraryData) {
return model;
} else {
return emitErrors ? filterErrorElements(model) : 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;
}
}
public final M parse(Element element) {
return parse(element, true);
}
protected M filterErrorElements(M model) {
return model.hasErrors() ? null : model;
}
protected abstract M parse(Element element, List<AnnotationMirror> mirror);
public abstract DeclaredType getAnnotationType();
public DeclaredType getRepeatAnnotationType() {
return null;
}
public boolean isDelegateToRootDeclaredType() {
return false;
}
public List<DeclaredType> getAllAnnotationTypes() {
List<DeclaredType> list = new ArrayList<>();
if (getAnnotationType() != null) {
list.add(getAnnotationType());
}
list.addAll(getTypeDelegatedAnnotationTypes());
return list;
}
public List<DeclaredType> getTypeDelegatedAnnotationTypes() {
return Collections.emptyList();
}
}