
src.ecjTransformer.lombok.ast.ecj.EcjTreePrinter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lombok-ast Show documentation
Show all versions of lombok-ast Show documentation
This is a very small fork of lombok.ast as some Android tools needed a few modifications. The normal repository for lombok.ast is here https://github.com/rzwitserloot/lombok.ast and our changes for 0.2.3 are in this pull request: https://github.com/rzwitserloot/lombok.ast/pull/8
The newest version!
/*
* Copyright (C) 2010 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package lombok.ast.ecj;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.val;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import com.google.common.base.Joiner;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.MapMaker;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
public class EcjTreePrinter {
private static final Multimap, ComponentField> visitedClasses = ArrayListMultimap.create();
private static final List POSITION_FIELDNAMES = ImmutableList.of(
"sourceStart",
"sourceEnd",
"originalSourceEnd",
"bodyStart",
"bodyEnd",
"blockStart",
"declarationSourceStart",
"declarationSourceEnd",
"declarationEnd",
"endPart1Position",
"endPart2Position",
"valuePositions",
"sourcePositions",
"modifiersSourceStart",
"typeArgumentsSourceStart",
"statementEnd",
"labelEnd",
"nameSourcePosition",
"tagSourceStart",
"tagSourceEnd"
);
private final Printer printer;
private Set propertySkipList = Sets.newHashSet();
private Multimap propertyIfValueSkipList = ArrayListMultimap.create();
private Map stringReplacements = Maps.newHashMap();
private List referenceTrackingSkipList = Lists.newArrayList();
private EcjTreePrinter(boolean printPositions) {
printer = new Printer(printPositions);
}
public static EcjTreePrinter printerWithPositions() {
return new EcjTreePrinter(true);
}
public static EcjTreePrinter printerWithoutPositions() {
return new EcjTreePrinter(false);
}
@Override
public String toString() {
return getContent();
}
public String getContent() {
String result = printer.content.toString();
for (val entry : stringReplacements.entrySet()) {
result = result.replace(entry.getKey(), entry.getValue());
}
return result;
}
public void visit(ASTNode node) {
visitor.visitEcjNode(node);
}
public EcjTreePrinter skipProperty(Class extends ASTNode> type, String propertyName) {
propertySkipList.add(type.getSimpleName() + "/" + propertyName);
return this;
}
public EcjTreePrinter skipPropertyIfHasValue(Class extends ASTNode> type, String propertyName, Object value) {
propertyIfValueSkipList.put(type.getSimpleName() + "/" + propertyName, value);
return this;
}
public void stringReplace(String original, String replacement) {
stringReplacements.put(original, replacement);
}
@Data
private static class ReferenceTrackingSkip {
private final Class extends ASTNode> parent;
private final Class> type;
}
public EcjTreePrinter skipReferenceTracking(Class extends ASTNode> parent, Class> type) {
referenceTrackingSkipList.add(new ReferenceTrackingSkip(parent, type));
return this;
}
private final EcjTreeVisitor visitor = new EcjTreeVisitor() {
@Override public void visitAny(ASTNode node) {
Collection fields = findFields(node);
for (ComponentField f : fields) {
String skipListKey = node.getClass().getSimpleName() + "/" + f.field.getName();
if (propertySkipList.contains(skipListKey)) continue;
Object value;
if (node instanceof ConditionalExpression) ((ConditionalExpression)node).valueIfTrue.sourceEnd = -2;
if ("originalSourceEnd".equals(f.field.getName()) && node instanceof ArrayTypeReference) {
//workaround for eclipse arbitrarily skipping this field and setting it.
value = -2;
} else {
value = readField(f.field, node);
}
if (value == null) {
continue;
}
if (propertyIfValueSkipList.get(skipListKey).contains(value)) continue;
boolean trackRef = true;
for (ReferenceTrackingSkip skip : referenceTrackingSkipList) {
if (skip.getParent() != null && !skip.getParent().isInstance(node)) continue;
if (skip.getType() != null && !skip.getType().isInstance(value)) continue;
trackRef = false;
break;
}
f.print(printer, this, value, trackRef);
}
}
//TODO all the javadocy nodes need to be as methods in EcjTreeVisitor.
@Override
public void visitOther(ASTNode node) {
visitAny(node);
}
};
@SneakyThrows(IllegalAccessException.class)
private Object readField(Field field, ASTNode node) {
return field.get(node);
}
private static Collection findFields(ASTNode node) {
Class extends ASTNode> clazz = node.getClass();
if (visitedClasses.containsKey(clazz)) {
return visitedClasses.get(clazz);
}
List fields = Lists.newArrayList();
for (Field f : findAllFields(clazz)) {
if ((f.getModifiers() & Modifier.STATIC) != 0) continue;
fields.add(new ComponentField(f));
}
Collections.sort(fields);
visitedClasses.putAll(clazz, fields);
return fields;
}
private static List findAllFields(Class> clazz) {
List allFields = Lists.newArrayList();
findAllFieldsRecursively(allFields, clazz);
return allFields;
}
private static void findAllFieldsRecursively(List allFields, Class> clazz) {
if (clazz == Object.class) {
return;
}
allFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
findAllFieldsRecursively(allFields, clazz.getSuperclass());
}
static class Printer {
final Map
© 2015 - 2025 Weber Informatics LLC | Privacy Policy