/**
* Copyright (C) 2006-2017 INRIA and contributors
* Spoon - http://spoon.gforge.inria.fr/
*
* This software is governed by the CeCILL-C License under French law and
* abiding by the rules of distribution of free software. You can use, modify
* and/or redistribute the software under the terms of the CeCILL-C license as
* circulated by CEA, CNRS and INRIA at http://www.cecill.info.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL-C license and that you accept its terms.
*/
package spoon.reflect.visitor;
import spoon.reflect.code.CtExpression;
import spoon.reflect.declaration.CtElement;
import spoon.reflect.declaration.CtType;
import spoon.reflect.reference.CtTypeReference;
import java.util.ArrayDeque;
import java.util.Deque;
public class PrintingContext {
private long NO_TYPE_DECL = 1 << 0;
private long IGNORE_GENERICS = 1 << 1;
private long SKIP_ARRAY = 1 << 2;
private long IGNORE_STATIC_ACCESS = 1 << 3;
private long IGNORE_ENCLOSING_CLASS = 1 << 4;
private long state;
public boolean noTypeDecl() {
return (state & NO_TYPE_DECL) != 0L;
}
public boolean ignoreGenerics() {
return (state & IGNORE_GENERICS) != 0L;
}
public boolean skipArray() {
return (state & SKIP_ARRAY) != 0L;
}
public boolean ignoreStaticAccess() {
return (state & IGNORE_STATIC_ACCESS) != 0L;
}
public boolean ignoreEnclosingClass() {
return (state & IGNORE_ENCLOSING_CLASS) != 0L;
}
public class Writable implements AutoCloseable {
private long oldState;
protected Writable() {
oldState = state;
}
@Override
public void close() {
state = oldState;
}
public <T extends Writable> T noTypeDecl(boolean v) {
setState(NO_TYPE_DECL, v);
return (T) this;
}
public <T extends Writable> T ignoreGenerics(boolean v) {
setState(IGNORE_GENERICS, v);
return (T) this;
}
public <T extends Writable> T skipArray(boolean v) {
setState(SKIP_ARRAY, v);
return (T) this;
}
public <T extends Writable> T ignoreStaticAccess(boolean v) {
setState(IGNORE_STATIC_ACCESS, v);
return (T) this;
}
public <T extends Writable> T ignoreEnclosingClass(boolean v) {
setState(IGNORE_ENCLOSING_CLASS, v);
return (T) this;
}
private void setState(long mask, boolean v) {
state = v ? state | mask : state & ~mask;
}
}
public Writable modify() {
return new Writable();
}
Deque<TypeContext> currentThis = new ArrayDeque<>();
/**
* @return top level type
*/
public CtTypeReference<?> getCurrentTypeReference() {
if (currentTopLevel != null) {
TypeContext tc = getCurrentTypeContext();
if (tc != null) {
return tc.typeRef;
}
return currentTopLevel.getReference();
}
return null;
}
private TypeContext getCurrentTypeContext() {
if (currentThis != null && currentThis.size() > 0) {
TypeContext tc = currentThis.peek();
return tc;
}
return null;
}
public void pushCurrentThis(CtType<?> type) {
currentThis.push(new TypeContext(type));
}
public void popCurrentThis() {
currentThis.pop();
}
Deque<CtElement> elementStack = new ArrayDeque<>();
Deque<CtExpression<?>> parenthesedExpression = new ArrayDeque<>();
CtType<?> currentTopLevel;
@Override
public String toString() {
return "context.ignoreGenerics: " + ignoreGenerics() + "\n";
}
/**
* @param typeRef
* @return true if typeRef is equal to current (actually printed) Type (currentThis)
*/
public boolean isInCurrentScope(CtTypeReference<?> typeRef) {
CtTypeReference<?> currentTypeRef = getCurrentTypeReference();
return currentTypeRef != null && typeRef.equals(currentTypeRef);
}
}