org.apache.calcite.linq4j.tree.ExpressionWriter Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.calcite.linq4j.tree;
import org.apache.calcite.avatica.util.Spacer;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.lang.reflect.Type;
import java.util.Iterator;
/**
* Converts an expression to Java code.
*/
class ExpressionWriter {
/** How many spaces to indent Java code. */
private static final int INDENT = 2;
private final Spacer spacer = new Spacer(0);
private final StringBuilder buf = new StringBuilder();
private boolean indentPending;
private final boolean generics;
ExpressionWriter() {
this(true);
}
ExpressionWriter(boolean generics) {
this.generics = generics;
}
public void write(Node expression) {
if (expression instanceof Expression) {
Expression expression1 = (Expression) expression;
expression1.accept(this, 0, 0);
} else {
expression.accept(this);
}
}
@Override public String toString() {
return buf.toString();
}
/**
* If parentheses are required, writes this expression out with
* parentheses and returns true. If they are not required, does nothing
* and returns false.
*/
public boolean requireParentheses(Expression expression, int lprec,
int rprec) {
if (lprec < expression.nodeType.lprec
&& expression.nodeType.rprec >= rprec) {
return false;
}
buf.append("(");
expression.accept(this, 0, 0);
buf.append(")");
return true;
}
/**
* Increases the indentation level.
*/
public void begin() {
spacer.add(INDENT);
}
/**
* Decreases the indentation level.
*/
public void end() {
spacer.subtract(INDENT);
}
public ExpressionWriter newlineAndIndent() {
buf.append("\n");
indentPending = true;
return this;
}
public ExpressionWriter indent() {
spacer.spaces(buf);
return this;
}
public ExpressionWriter begin(String s) {
append(s);
begin();
indentPending = s.endsWith("\n");
return this;
}
public ExpressionWriter end(String s) {
end();
append(s);
indentPending = s.endsWith("\n");
return this;
}
public ExpressionWriter append(char c) {
checkIndent();
buf.append(c);
return this;
}
public ExpressionWriter append(Type type) {
checkIndent();
if (!generics) {
type = Types.stripGenerics(type);
}
buf.append(Types.className(type));
return this;
}
public ExpressionWriter append(AbstractNode o) {
o.accept0(this);
return this;
}
public ExpressionWriter append(@Nullable Object o) {
checkIndent();
buf.append(o);
return this;
}
public ExpressionWriter append(@Nullable String s) {
checkIndent();
buf.append(s);
return this;
}
private void checkIndent() {
if (indentPending) {
spacer.spaces(buf);
indentPending = false;
}
}
public StringBuilder getBuf() {
checkIndent();
return buf;
}
public ExpressionWriter list(String begin, String sep, String end,
Iterable> list) {
final Iterator> iterator = list.iterator();
if (iterator.hasNext()) {
begin(begin);
for (;;) {
Object o = iterator.next();
if (o instanceof Expression) {
((Expression) o).accept(this, 0, 0);
} else if (o instanceof MemberDeclaration) {
((MemberDeclaration) o).accept(this);
} else if (o instanceof Type) {
append((Type) o);
} else {
append(o);
}
if (!iterator.hasNext()) {
break;
}
buf.append(sep);
if (sep.endsWith("\n")) {
indentPending = true;
}
}
end(end);
} else {
while (begin.endsWith("\n")) {
begin = begin.substring(0, begin.length() - 1);
}
buf.append(begin).append(end);
}
return this;
}
public void backUp() {
if (buf.lastIndexOf("\n") == buf.length() - 1) {
buf.delete(buf.length() - 1, buf.length());
indentPending = false;
}
}
}