/** * */ package de.ovgu.cide.configuration.jdt; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Set; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTNode; 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 de.ovgu.cide.configuration.ConfigurationException; import de.ovgu.cide.features.IFeature; import de.ovgu.cide.features.source.ColoredSourceFile; import de.ovgu.cide.language.jdt.JDTParserWrapper; public class DeleteHiddenNodesVisitor extends ASTVisitor { public static String hideCode(ColoredSourceFile source, Collection<IFeature> selectedColors) throws ConfigurationException { try { ICompilationUnit compUnit = JDTParserWrapper .getICompilationUnit(source.getResource()); assert compUnit != null; CompilationUnit ast = JDTParserWrapper.parseJavaFile(source .getResource()); assert ast != null; return hideCode(compUnit.getBuffer().getContents(), ast, new JDTColorManagerBridge(source.getColorManager(), source .getResource()), selectedColors); } catch (Exception e) { throw new ConfigurationException(e); } } public static String hideCode(String buffer, CompilationUnit ast, JDTColorManagerBridge nodeColors, Collection<IFeature> visibleColors) throws JavaModelException, IllegalArgumentException { Set<IFeature> compUnitColors = nodeColors.getColors(ast); for (IFeature color : compUnitColors) if (!visibleColors.contains(color)) return ""; ASTRewrite rewrite = ASTRewrite.create(ast.getAST()); ast.accept(new DeleteHiddenNodesVisitor(rewrite, nodeColors, visibleColors)); 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(); } private ASTRewrite rewrite; protected Collection<IFeature> selectedColors; protected JDTColorManagerBridge colorManager; public DeleteHiddenNodesVisitor(ASTRewrite rewrite, JDTColorManagerBridge nodeColors, Collection<IFeature> selectedColors) { this.rewrite = rewrite; this.colorManager = nodeColors; this.selectedColors = selectedColors; } @Override public boolean visit(InfixExpression node) { // TODO Auto-generated method stub return super.visit(node); } public void postVisit(ASTNode node) { if (shouldHide(node)) { // are there children that should not be deleted as well? List<ASTNode> replacements = new ArrayList<ASTNode>(); for (Object prop : node.structuralPropertiesForType()) { if (ASTColorInheritance.notInheritedProperties.contains(prop)) { Object replace = rewrite.get(node, (StructuralPropertyDescriptor) prop); Object originalValue = node .getStructuralProperty((StructuralPropertyDescriptor) prop); if (replace instanceof ASTNode) if (!(originalValue instanceof ASTNode) || !shouldHide((ASTNode) originalValue)) replacements.add((ASTNode) replace); } } remove(node, replacements); } } private boolean shouldHide(ASTNode node) { Set<IFeature> nodeColors = colorManager.getOwnColors(node); for (IFeature color : nodeColors) if (!selectedColors.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(ASTNode node, List<ASTNode> replacements) { ASTNode 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(ASTNode node, InfixExpression parent, StructuralPropertyDescriptor prop, List<ASTNode> replacements) { ASTNode 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(ASTNode node, ASTNode parent, StructuralPropertyDescriptor prop, List<ASTNode> replacements) { Block replacement = node.getAST().newBlock(); rewrite.set(parent, prop, replacement, null); if (replacements.size() > 0) { ListRewrite blockRewriteList = getRewriteList(replacement, Block.STATEMENTS_PROPERTY); for (ASTNode s : replacements) for (ASTNode n : resolveBlock(s)) { blockRewriteList.insertLast(move(n), null); } } else if (prop == IfStatement.ELSE_STATEMENT_PROPERTY) rewrite.set(parent, prop, null, null); } private void rewriteListChild(ASTNode node, ASTNode parent, ChildListPropertyDescriptor prop, List<ASTNode> 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 (ASTNode repl : replacements) { if (!parentBlock) { statementsListRewrite .insertAt(move(repl), ++position, null); } else { for (ASTNode s : resolveBlock(repl)) statementsListRewrite.insertAt(move(s), ++position, null); } } } } private ASTNode move(ASTNode s) { if (s.getStartPosition() != -1) return rewrite.createMoveTarget(s); return s; } private List<ASTNode> resolveBlock(ASTNode replacement) { if (replacement instanceof Block) { ListRewrite rewrittenBlock = getRewriteList(replacement, Block.STATEMENTS_PROPERTY); List l = rewrittenBlock.getRewrittenList(); if (replacement.getStartPosition() == -1) return new ArrayList<ASTNode>();// TODO debugging only return l; } return Collections.singletonList(replacement); } private final HashMap<ASTNode, HashMap<ChildListPropertyDescriptor, ListRewrite>> knownRewriteLists = new HashMap<ASTNode, HashMap<ChildListPropertyDescriptor, ListRewrite>>(); private ListRewrite getRewriteList(ASTNode 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; } }