/** * */ package coloredide.configuration; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Set; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.IASTNode; import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.Block; import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor; import org.eclipse.jdt.core.dom.ChildPropertyDescriptor; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.IfStatement; import org.eclipse.jdt.core.dom.InfixExpression; import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor; import org.eclipse.jdt.core.dom.InfixExpression.Operator; import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; import org.eclipse.jdt.core.dom.rewrite.ListRewrite; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.Document; import org.eclipse.text.edits.MalformedTreeException; import org.eclipse.text.edits.TextEdit; import coloredide.features.ASTColorInheritance; import coloredide.features.Feature; import coloredide.features.source.ColoredJavaSourceFile; import coloredide.features.source.CompilationUnitColorManager; public class DeleteHiddenNodesVisitor extends ASTVisitor { private ASTRewrite rewrite; protected Set<Feature> hiddenColors; protected CompilationUnitColorManager colorManager; public DeleteHiddenNodesVisitor(ASTRewrite rewrite, CompilationUnitColorManager nodeColors, Set<Feature> hiddenColors) { this.rewrite = rewrite; this.colorManager = nodeColors; this.hiddenColors = hiddenColors; } @Override public boolean visit(InfixExpression node) { // TODO Auto-generated method stub return super.visit(node); } public void postVisit(IASTNode node) { if (shouldHide(node)) { // are there children that should not be deleted as well? List<IASTNode> replacements = new ArrayList<IASTNode>(); for (Object prop : node.structuralPropertiesForType()) { if (ASTColorInheritance.notInheritedProperties.contains(prop)) { Object replace = rewrite.get(node, (StructuralPropertyDescriptor) prop); if (replace instanceof IASTNode) replacements.add((IASTNode) replace); } } remove(node, replacements); } } private boolean shouldHide(IASTNode node) { Set<Feature> nodeColors = colorManager.getOwnColors(node); for (Feature color : nodeColors) if (hiddenColors.contains(color)) return true; return false; } /** * deletes the node and replaced it with the replacement-list if not empty * or null if only one single property can be replaced only the first of the * list is inserted. * * @param node * not null * @param replacements * not null */ private void remove(IASTNode node, List<IASTNode> replacements) { IASTNode parent = node.getParent(); StructuralPropertyDescriptor prop = node.getLocationInParent(); if (prop instanceof ChildListPropertyDescriptor) { rewriteListChild(node, parent, (ChildListPropertyDescriptor) prop, replacements); } if (prop instanceof ChildPropertyDescriptor) { if (ASTColorInheritance.notInheritedProperties.contains(prop)) { rewriteIfWhileEtc(node, parent, prop, replacements); } else if (parent instanceof InfixExpression) { rewriteInfix(node, (InfixExpression) parent, prop, replacements); } } } private void rewriteInfix(IASTNode node, InfixExpression parent, StructuralPropertyDescriptor prop, List<IASTNode> replacements) { // ListRewrite extOperands = rewrite.getListRewrite(parent, // InfixExpression.EXTENDED_OPERANDS_PROPERTY); // if (extOperands.getRewrittenList().size() > 0) { // // if more than two operands, just shift. // IASTNode first = (IASTNode) extOperands.getRewrittenList().get(0); // extOperands.remove(first, null); // if (prop == InfixExpression.LEFT_OPERAND_PROPERTY) { // IASTNode right = (IASTNode) rewrite.get(parent, // InfixExpression.RIGHT_OPERAND_PROPERTY); // rewrite.set(parent, InfixExpression.LEFT_OPERAND_PROPERTY, // rewrite.createMoveTarget(right), null); // } // rewrite.set(parent, InfixExpression.RIGHT_OPERAND_PROPERTY, rewrite // .createMoveTarget(first), null); // } else { // // otherwise remove infixexpression // IASTNode value = (IASTNode) rewrite // .get( // parent, // (prop == InfixExpression.RIGHT_OPERAND_PROPERTY ? // InfixExpression.LEFT_OPERAND_PROPERTY // : InfixExpression.RIGHT_OPERAND_PROPERTY)); // rewrite.set(parent.getParent(), parent.getLocationInParent(), // rewrite.createMoveTarget(value), null); // } IASTNode defaultValue = null; AST ast = rewrite.getAST(); if (parent.getOperator() == Operator.CONDITIONAL_AND) defaultValue = ast.newBooleanLiteral(true); else if (parent.getOperator() == Operator.CONDITIONAL_OR) defaultValue = ast.newBooleanLiteral(false); else if (parent.getOperator() == Operator.PLUS || parent.getOperator() == Operator.MINUS || parent.getOperator() == Operator.LEFT_SHIFT || parent.getOperator() == Operator.RIGHT_SHIFT_SIGNED || parent.getOperator() == Operator.RIGHT_SHIFT_UNSIGNED) defaultValue = ast.newNumberLiteral("0"); if (defaultValue != null) rewrite.set(parent, prop, defaultValue, null); } private void rewriteIfWhileEtc(IASTNode node, IASTNode parent, StructuralPropertyDescriptor prop, List<IASTNode> replacements) { Block replacement = node.getAST().newBlock(); rewrite.set(parent, prop, replacement, null); if (replacements.size() > 0) { ListRewrite blockRewriteList = getRewriteList(replacement, Block.STATEMENTS_PROPERTY); for (IASTNode s : replacements) for (IASTNode n : resolveBlock(s)) { blockRewriteList.insertLast(move(n), null); } } else if (prop == IfStatement.ELSE_STATEMENT_PROPERTY) rewrite.set(parent, prop, null, null); } private void rewriteListChild(IASTNode node, IASTNode parent, ChildListPropertyDescriptor prop, List<IASTNode> replacements) { ListRewrite statementsListRewrite = getRewriteList(parent, prop); int position = statementsListRewrite.getRewrittenList().indexOf(node); statementsListRewrite.remove(node, null); // replacements? if (replacements.size() > 0) { boolean parentBlock = parent instanceof Block; for (IASTNode repl : replacements) { if (!parentBlock) { statementsListRewrite .insertAt(move(repl), ++position, null); } else { for (IASTNode s : resolveBlock(repl)) statementsListRewrite.insertAt(move(s), ++position, null); } } } } private IASTNode move(IASTNode s) { if (s.getStartPosition() != -1) return rewrite.createMoveTarget(s); return s; } // ListRewrite statementsListRewrite = getRewriteList(node); // if (statementsListRewrite != null) { // int position = statementsListRewrite.getRewrittenList().indexOf( // node); // statementsListRewrite.remove(node, null); // if (replacements != null && replacements.size() > 0) { // if (node.getParent() instanceof Block) // replacements = resolveBlock(replacements); // for (int idx = replacements.size() - 1; idx >= 0; idx--) // statementsListRewrite.insertAt((IASTNode) replacements // .get(idx), position, null); // } // } else { // StructuralPropertyDescriptor prop = node.getLocationInParent(); // if (prop == IfStatement.THEN_STATEMENT_PROPERTY // || prop == IfStatement.ELSE_STATEMENT_PROPERTY) { // Block replacement = node.getAST().newBlock(); // rewrite.set(node.getParent(), node.getLocationInParent(), // replacement, null); // ListRewrite blockRewriteList = getRewriteList(replacement, // Block.STATEMENTS_PROPERTY); // for (IASTNode s : replacements) // for (IASTNode n : resolveBlock(s)) // blockRewriteList.insertLast(n, null); // } // // } // } // private ListRewrite getRewriteList(IASTNode node) { // IASTNode parent = node.getParent(); // StructuralPropertyDescriptor property = node.getLocationInParent(); // if (property instanceof ChildListPropertyDescriptor) // return getRewriteList(parent, // (ChildListPropertyDescriptor) property); // return null; // } // private List<IASTNode> resolveBlock(List<IASTNode> replacement) { // if (replacement.size() == 1 && replacement.get(0) instanceof Block) // return ((Block) replacement.get(0)).statements(); // return replacement; // } private List<IASTNode> resolveBlock(IASTNode replacement) { if (replacement instanceof Block) { ListRewrite rewrittenBlock = getRewriteList(replacement, Block.STATEMENTS_PROPERTY); List l = rewrittenBlock.getRewrittenList(); if (replacement.getStartPosition() == -1) return new ArrayList<IASTNode>();//TODO debugging only return l; } return Collections.singletonList(replacement); } private final HashMap<IASTNode, HashMap<ChildListPropertyDescriptor, ListRewrite>> knownRewriteLists = new HashMap<IASTNode, HashMap<ChildListPropertyDescriptor, ListRewrite>>(); private ListRewrite getRewriteList(IASTNode parent, ChildListPropertyDescriptor descriptor) { HashMap<ChildListPropertyDescriptor, ListRewrite> known = knownRewriteLists .get(parent); ListRewrite knownList = null; if (known != null) { knownList = known.get(descriptor); if (knownList != null) return knownList; } knownList = rewrite.getListRewrite(parent, descriptor); if (known == null) { known = new HashMap<ChildListPropertyDescriptor, ListRewrite>(); known.put(descriptor, knownList); } knownRewriteLists.put(parent, known); return knownList; } public static String hideCode(ColoredJavaSourceFile source, Set<Feature> hiddenColors) throws CoreException { return hideCode(source.getCompilationUnit().getBuffer().getContents(), source.getAST(), source.getColorManager(), hiddenColors); } public static String hideCode(String buffer, CompilationUnit ast, CompilationUnitColorManager nodeColors, Set<Feature> hiddenColors) throws CoreException { Set<Feature> compUnitColors = nodeColors.getColors(ast); for (Feature color : compUnitColors) if (hiddenColors.contains(color)) return ""; ASTRewrite rewrite = ASTRewrite.create(ast.getAST()); ast.accept(new DeleteHiddenNodesVisitor(rewrite, nodeColors, hiddenColors)); TextEdit r = rewrite.rewriteAST(); Document document = new Document(buffer); try { r.apply(document); } catch (MalformedTreeException e) { e.printStackTrace(); } catch (BadLocationException e) { e.printStackTrace(); } return document.get(); } }