package de.ovgu.cide.editor; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.Stack; import cide.gast.ASTVisitor; import cide.gast.IASTNode; import cide.gast.IASTVisitor; import de.ovgu.cide.features.IFeature; import de.ovgu.cide.features.source.SourceFileColorManager; public class CodeSegmentCalculator { protected static final Set<IFeature> NOCOLORS = new HashSet<IFeature>(); public static List<CodeSegment> getCodeSegments(IASTNode ast, final SourceFileColorManager colorManager) { final Stack<CodeSegment> stack = new Stack<CodeSegment>(); final List<CodeSegment> list = new ArrayList<CodeSegment>(); stack.push(new CodeSegment(ast.getStartPosition(), ast .getStartPosition() + ast.getLength(), NOCOLORS, false)); IASTVisitor visitor = new ASTVisitor() { private IASTNode last; public boolean visit(IASTNode node) { IASTNode next = node; node = last; last = next; if (node == null) return true; if (node.getLength()==0) return true; while (stack.peek().endPosition() <= node.getStartPosition()) list.add(stack.pop()); Set<IFeature> colors = colorManager.getColors(node); if (stack.peek().getColors().equals(colors)) { // colors did not change, ignore // stack.peek().containingNodes.add(node); } else { CodeSegment old = stack.pop(); // finished previous segment assert old.getOffset() <= node.getStartPosition(); list.add(new CodeSegment(old.getOffset(), node .getStartPosition(), old.getColors(), false)); assert node.getStartPosition() + node.getLength() <= old .endPosition(); stack.push(new CodeSegment(node.getStartPosition() + node.getLength(), old.endPosition(), old.getColors(), false)); assert node.getStartPosition() <= node.getStartPosition() + node.getLength(); stack.push(new CodeSegment(node.getStartPosition(), node .getStartPosition() + node.getLength(), colors, false)); // stack.peek().containingNodes.add(node); } return super.visit(node); } }; ast.accept(visitor); while (!stack.isEmpty()) list.add(stack.pop()); removeEmptySegments(list); return list; } private static void removeEmptySegments(List<CodeSegment> list) { Iterator<CodeSegment> i = list.iterator(); while (i.hasNext()) { CodeSegment seg = i.next(); if (seg.isEmpty()) { i.remove(); } } } }