package org.inferred.freebuilder.processor.util;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Maps.newLinkedHashMap;
import org.inferred.freebuilder.processor.util.feature.Feature;
import org.inferred.freebuilder.processor.util.feature.FeatureType;
import java.util.Map;
/**
* A Block contains a preamble of lazily-added declarations followed by a body.
*/
public class Block extends Excerpt implements SourceBuilder {
private final Map<String, Excerpt> declarations = newLinkedHashMap();
private final SourceStringBuilder body;
public Block(SourceBuilder parent) {
body = parent.subBuilder();
}
/**
* Declare {@code name} in this block's preamble, returning an Excerpt to use it. Duplicate
* declarations will be elided.
*
* @throws IllegalStateException if {@code name} has already been added to this block with a
* different declaration
*/
public Excerpt declare(final String name, final String declfmt, final Object... declArgs) {
Excerpt declaration = Excerpts.add(declfmt, declArgs);
Excerpt existingDeclaration = declarations.put(name, declaration);
checkState(existingDeclaration == null || declaration.equals(existingDeclaration),
"Incompatible declaration for '%s': %s vs %s",
name,
declaration,
existingDeclaration);
return Excerpts.add("%s", name);
}
@Override
public Block add(String fmt, Object... args) {
body.add(fmt, args);
return this;
}
@Override
public Block addLine(String fmt, Object... args) {
body.addLine(fmt, args);
return this;
}
@Override
public Block add(Excerpt excerpt) {
body.add(excerpt);
return this;
}
@Override
public SourceStringBuilder subBuilder() {
return body.subBuilder();
}
@Override
public <T extends Feature<T>> T feature(FeatureType<T> featureType) {
return body.feature(featureType);
}
@Override
public void addTo(SourceBuilder source) {
for (Excerpt declaration : declarations.values()) {
source.add(declaration);
}
source.add("%s", body);
}
@Override
protected void addFields(FieldReceiver fields) {
fields.add("declarations", declarations);
fields.add("body", body.toString());
}
}