/** * Builds the FSTModel of the feature project and creates a list of all directives with valid * colors * * @return the directive list */ private void createDirectiveList() { directiveMap.clear(); validDirectiveList.clear(); FSTModel model = project.getFSTModel(); if (model == null) { composer.buildFSTModel(); model = project.getFSTModel(); } if (model == null) { return; } int index = 0; for (FSTFeature fstFeature : model.getFeatures()) { for (FSTRole role : fstFeature.getRoles()) { if (file.equals(role.getFile())) { for (FSTDirective dir : role.getDirectives()) { directiveMap.put(dir.getId(), dir); index++; } } } } for (int i = 0; i < index; i++) { FSTDirective dir = directiveMap.get(i); if (dir != null && ColorList.isValidColor(dir.getColor())) { validDirectiveList.add(dir); } } }
private int getLastChildLine(FSTDirective directive, int lastLine) { for (FSTDirective child : directive.getChildren()) { int childEnd = child.getEndLine(); if (child.getEndLength() > 0) { childEnd++; } lastLine = Math.max(childEnd, lastLine); lastLine = Math.max(getLastChildLine(child, lastLine), lastLine); } return lastLine; }
private boolean hasChildAtLine(FSTDirective directive, int line, boolean hasValidColor) { for (FSTDirective child : directive.getChildren()) { int start = child.getStartLine(); int end = child.getEndLine(); if (line >= start && line <= end && (!hasValidColor || child.getColor() != FeatureColor.NO_COLOR.getValue())) { return true; } if (hasChildAtLine(child, line, hasValidColor)) { return true; } } return false; }
/** Creates a new overview ruler annotation. */ private void createOverViewRuler( AnnotationModelEvent event, FSTDirective directive, final int color, Position newPos) { ColorAnnotation ca = new ColorAnnotation(color, newPos, ColorAnnotation.TYPE_OVERVIEW); ca.setText(directive.toString()); annotations.add(ca); event.annotationAdded(ca); }
/** * Builds the FSTModel of the feature project and creates a list of all directives with valid * colors * * @return the directive list */ private void createDirectiveList() { directiveMap.clear(); validDirectiveList.clear(); FSTModel model = project.getFSTModel(); if (model == null || model.getClasses().isEmpty()) { composer.buildFSTModel(); model = project.getFSTModel(); } if (model == null) { return; } for (FSTFeature fstFeature : model.getFeatures()) { for (FSTRole role : fstFeature.getRoles()) { if (file.equals(role.getFile())) { for (FSTDirective dir : role.getDirectives()) { directiveMap.put(dir.getId(), dir); validDirectiveList.add(dir); } } } } }
@Override public LinkedList<FSTDirective> buildModelDirectivesForFile(Vector<String> lines) { // for preprocessor outline Stack<FSTDirective> directivesStack = new Stack<FSTDirective>(); LinkedList<FSTDirective> directivesList = new LinkedList<FSTDirective>(); int id = 0; for (int i = 0; i < lines.size(); i++) { String line = lines.get(i); // if line is preprocessor directive if (containsRegex(line, "//\\s*#")) { FSTDirectiveCommand command = null; if (containsRegex(line, "//\\s*#if[ (]")) { // 1 command = FSTDirectiveCommand.IF; } else if (containsRegex(line, "//\\s*#ifdef[ (]")) { // 2 command = FSTDirectiveCommand.IFDEF; } else if (containsRegex(line, "//\\s*#ifndef[ (]")) { // 3 command = FSTDirectiveCommand.IFNDEF; } else if (containsRegex(line, "//\\s*#elif[ (]")) { // 4 command = FSTDirectiveCommand.ELIF; } else if (containsRegex(line, "//\\s*#elifdef[ (]")) { // 5 command = FSTDirectiveCommand.ELIFDEF; } else if (containsRegex(line, "//\\s*#elifndef[ (]")) { // 6 command = FSTDirectiveCommand.ELIFNDEF; } else if (containsRegex(line, "//\\s*#else")) { // 7 command = FSTDirectiveCommand.ELSE; } else if (containsRegex(line, "//\\s*#condition[ (]")) { // 8 command = FSTDirectiveCommand.CONDITION; } else if (containsRegex(line, "//\\s*#define[ (]")) { // 9 command = FSTDirectiveCommand.DEFINE; } else if (containsRegex(line, "//\\s*#undefine[ (]")) { // 10 command = FSTDirectiveCommand.UNDEFINE; } else if (!containsRegex(line, "//\\s*#endif")) { // 11 continue; } if (command == null) { if (!directivesStack.isEmpty()) { directivesStack.peek().setEndLine(i, line.length()); while (!directivesStack.isEmpty()) { FSTDirective parent = directivesStack.pop(); if (parent.getCommand() != FSTDirectiveCommand.ELIF && parent.getCommand() != FSTDirectiveCommand.ELIFDEF && parent.getCommand() != FSTDirectiveCommand.ELIFNDEF && parent.getCommand() != FSTDirectiveCommand.ELSE) { break; } } } } else { FSTDirective directive = new FSTDirective(); if (command == FSTDirectiveCommand.ELSE) { if (!directivesStack.isEmpty()) { directivesStack.peek().setEndLine(i, 0); directive.setFeatureName(directivesStack.peek().getFeatureName()); } } else if (command == FSTDirectiveCommand.ELIF || command == FSTDirectiveCommand.ELIFDEF || command == FSTDirectiveCommand.ELIFNDEF) { if (!directivesStack.isEmpty()) { directivesStack.peek().setEndLine(i, 0); } } directive.setCommand(command); Matcher m = patternCommands.matcher(line); line = m.replaceAll("").trim(); if (directive.getFeatureName() == null) { directive.setFeatureName(getFeatureName(line)); } directive.setExpression(line); directive.setStartLine(i, 0); directive.setId(id++); if (directivesStack.isEmpty()) { directivesList.add(directive); } else { directivesStack.peek().addChild(directive); } if (command != FSTDirectiveCommand.DEFINE && command != FSTDirectiveCommand.UNDEFINE && command != FSTDirectiveCommand.CONDITION) directivesStack.push(directive); } } } return directivesList; }
/** Creates the color annotations from the FSTDirectives. */ private void createAnnotations() { AnnotationModelEvent event = new AnnotationModelEvent(this); Iterator<FSTDirective> it = validDirectiveList.descendingIterator(); while (it.hasNext()) { FSTDirective dir = it.next(); try { int startline = dir.getStartLine(); int endline = dir.getEndLine(); for (int i = startline; i <= endline; i++) { if (i < endline || dir.getEndLength() > 0) { int lineLength = document.getLineLength(i); int lineOffset = document.getLineOffset(i); if (i == endline) { lineLength = dir.getEndLength(); } if (i == startline) { lineOffset += dir.getStartOffset(); lineLength -= dir.getStartOffset(); } Position newPos = new Position(lineOffset, lineLength); if (!annotatedPositions.containsKey(i)) { if (!ColorList.isValidColor(dir.getColor())) break; ColorAnnotation ca = new ColorAnnotation( dir.getColor(), new Position(lineOffset, lineLength), ColorAnnotation.TYPE_IMAGE); annotations.add(ca); event.annotationAdded(ca); if (highlighting) { ca = new ColorAnnotation( dir.getColor(), newPos, i == startline ? ColorAnnotation.TYPE_HIGHLIGHT_OVERVIEW : ColorAnnotation.TYPE_HIGHLIGHT); annotations.add(ca); event.annotationAdded(ca); } else if (i == startline) { ca = new ColorAnnotation(dir.getColor(), newPos, ColorAnnotation.TYPE_OVERVIEW); annotations.add(ca); event.annotationAdded(ca); } annotatedPositions.put(i, newPos); } else if (highlighting) { Position oldPos = annotatedPositions.get(i); int oldOffset = oldPos.getOffset(); int oldLength = oldPos.getLength(); int wholeOffset = oldOffset; int wholeLength = oldLength; if (oldOffset > lineOffset) { ColorAnnotation ca = new ColorAnnotation( dir.getColor(), new Position(lineOffset, oldOffset - lineOffset), ColorAnnotation.TYPE_HIGHLIGHT); annotations.add(ca); event.annotationAdded(ca); wholeOffset = lineOffset; wholeLength += oldOffset - lineOffset; } int newOffset = oldOffset + oldLength; int newLength = lineLength - (newOffset - lineOffset); if (newLength > 0) { newPos.setOffset(newOffset); newPos.setLength(newLength); ColorAnnotation ca = new ColorAnnotation(dir.getColor(), newPos, ColorAnnotation.TYPE_HIGHLIGHT); annotations.add(ca); event.annotationAdded(ca); wholeLength += newLength; } annotatedPositions.put(i, new Position(wholeOffset, wholeLength)); } } } } catch (BadLocationException e) { UIPlugin.getDefault().logError(e); } } fireModelChanged(event); }
/** * Assigns the mapped colors to the FSTDirectives from the changed document. * * @return the directive list */ private void updateDirectives() { ListIterator<FSTDirective> newDirIt = getNewDirectives().listIterator(0); while (newDirIt.hasNext()) { FSTDirective newDir = newDirIt.next(); FSTDirective oldDir = directiveMap.get(newDir.getId()); if (oldDir != null && newDir.getCommand() == oldDir.getCommand() && newDir.getFeatureName().equals(oldDir.getFeatureName())) { oldDir.setStartLine(newDir.getStartLine(), newDir.getStartOffset()); oldDir.setEndLine(newDir.getEndLine(), newDir.getEndLength()); } else { directiveMap.clear(); return; } if (newDir.hasChildren()) { for (FSTDirective newDirChild : newDir.getChildrenList()) { newDirIt.add(newDirChild); newDirIt.previous(); } } } }
/** Creates the color annotations from the FSTDirectives. */ private void createAnnotations() { AnnotationModelEvent event = new AnnotationModelEvent(this); for (FSTDirective directive : validDirectiveList) { if (directive == null) { continue; } try { int startline = directive.getStartLine(); int endline = getLastChildLine(directive, directive.getEndLine()); final int color = directive.getColor(); int overViewStartOffset = document.getLineOffset(startline); int overViewLength = 0; for (int line = startline; line <= endline; line++) { int length = document.getLineLength(line); if (line < endline || directive.getEndLength() > 0) { int lineOffset = document.getLineOffset(line); if (line == directive.getEndLine()) { length = directive.getEndLength(); } if (line == startline) { lineOffset += directive.getStartOffset(); length -= directive.getStartOffset(); } if (hasChildAtLine(directive, line)) { length = 1; } if (overViewStartOffset != -1 && hasChildAtLineWithColor(directive, line)) { Position overViewPos = new Position(overViewStartOffset, overViewLength); createOverViewRuler(event, directive, color, overViewPos); overViewStartOffset = -1; overViewLength = 0; } else if (!hasChildAtLineWithColor(directive, line)) { if (overViewStartOffset == -1) { overViewStartOffset = document.getLineOffset(line); } overViewLength += document.getLineLength(line); } FSTDirective parent = directive.getParent(); while (parent != null) { lineOffset++; if (length > 1) { length--; } parent = parent.getParent(); } Position newPos = new Position(lineOffset, length); if (!hasChildAtLine(directive, line)) { // bar at the left of the editor ColorAnnotation ca = new ColorAnnotation(color, newPos, ColorAnnotation.TYPE_IMAGE); ca.setText(directive.toString()); annotations.add(ca); event.annotationAdded(ca); } if (!hasChildAtLine(directive, line)) { // bar at the right of the editor } if (highlighting) { // background colors ColorAnnotation ca = new ColorAnnotation(color, newPos, ColorAnnotation.TYPE_HIGHLIGHT); ca.setText(directive.toDependencyString()); annotations.add(ca); event.annotationAdded(ca); } } } if (overViewStartOffset != -1) { Position overViewPos = new Position(overViewStartOffset, overViewLength); createOverViewRuler(event, directive, color, overViewPos); overViewStartOffset = -1; overViewLength = 0; } } catch (BadLocationException e) { LogService.getInstance().log(LogLevel.DEBUG, e.getMessage()); } } fireModelChanged(event); }
@Override public Object[] getChildren(Object parentElement) { Object[] obj = null; if (parentElement instanceof FSTClass) { // get all fields, methods, directives and invariants final TreeSet<FSTMethod> methods = new TreeSet<FSTMethod>(); final TreeSet<FSTField> fields = new TreeSet<FSTField>(); final TreeSet<FSTInvariant> invariants = new TreeSet<FSTInvariant>(); final TreeSet<FSTDirective> directives = new TreeSet<FSTDirective>(); final TreeSet<FSTClassFragment> innerClasses = new TreeSet<FSTClassFragment>(); for (FSTRole role : ((FSTClass) parentElement).getRoles()) { invariants.addAll(role.getClassFragment().getInvariants()); for (FSTMethod fstMethod : role.getMethods()) { if (fstMethod.getParent() instanceof FSTClassFragment) methods.add(fstMethod); } fields.addAll(role.getFields()); TreeSet<FSTDirective> roleDirectives = role.getDirectives(); for (FSTDirective directive : roleDirectives) { if (directive.getParent() == null) { directives.add(directive); } } innerClasses.addAll(role.getInnerClasses()); } obj = new IRoleElement [methods.size() + fields.size() + invariants.size() + directives.size() + innerClasses.size()]; int pos = 0; System.arraycopy(invariants.toArray(), 0, obj, pos, invariants.size()); System.arraycopy(fields.toArray(), 0, obj, pos += invariants.size(), fields.size()); System.arraycopy(methods.toArray(), 0, obj, pos += fields.size(), methods.size()); System.arraycopy(directives.toArray(), 0, obj, pos += methods.size(), directives.size()); System.arraycopy( innerClasses.toArray(), 0, obj, pos += directives.size(), innerClasses.size()); return filter(obj); } else if (parentElement instanceof FSTMethod) { // get all the roles that belong to a method Set<FSTRole> roleList = new HashSet<FSTRole>(); Set<FSTMethod> methods = new HashSet<FSTMethod>(); for (FSTRole role : ((FSTMethod) parentElement).getRole().getFSTClass().getRoles()) { for (FSTMethod m : role.getAllMethods()) { if ( // m.isOwn(role.file) && // ((FSTMethod)parentElement).isOwn(role.file) && m.getFullName().equals(((FSTMethod) parentElement).getFullName())) { if (m.hasContract()) { roleList.add( new FSTContractedRole(role.getFile(), role.getFeature(), role.getFSTClass())); } else { roleList.add(role); } methods.add(m); break; } } } List<String> featureOrder = CorePlugin.getFeatureProject(((FSTMethod) parentElement).getRole().getFile()) .getFeatureModel() .getFeatureOrderList(); if (((FSTMethod) parentElement).getFSTDirectives().size() == 0) { obj = new FSTRole[roleList.size()]; int index = 0; for (String featureName : featureOrder) { for (Iterator<FSTRole> it = roleList.iterator(); it.hasNext(); ) { FSTRole next = it.next(); if (next.getFeature().getName().equals(featureName)) { obj[index++] = next; it.remove(); break; } } } } else { List<FSTDirective> dirs = new ArrayList<>(); for (FSTRole role : roleList) { if (role.getMethods().contains(parentElement)) { // equals works correct? for (FSTMethod method : role.getMethods()) { if (method.equals(parentElement)) { dirs.addAll(method.getFSTDirectives()); break; } } } } return dirs.toArray(); } } else if (parentElement instanceof FSTInvariant) { // get all the roles that belong to an invariant LinkedList<FSTRole> roleList = new LinkedList<FSTRole>(); for (FSTRole role : ((FSTInvariant) parentElement).getRole().getFSTClass().getRoles()) { for (FSTInvariant i : role.getClassFragment().getInvariants()) { if (((FSTInvariant) parentElement).getFullName().equals(i.getFullName())) { roleList.add(role); break; } } } return filter(roleList.toArray()); } else if (parentElement instanceof FSTField) { // get all the roles that belong to a field LinkedList<FSTRole> roleList = new LinkedList<FSTRole>(); for (FSTRole role : ((FSTField) parentElement).getRole().getFSTClass().getRoles()) { for (FSTField f : role.getAllFields()) { if (f.getFullName().equals(((FSTField) parentElement).getFullName())) { roleList.add(role); break; } } } return filter(roleList.toArray()); } else if (parentElement instanceof FSTDirective) { return ((FSTDirective) parentElement).getRoleElementChildren(); } else if (parentElement instanceof FSTClassFragment) { final TreeSet<FSTMethod> methods = new TreeSet<FSTMethod>(); final TreeSet<FSTField> fields = new TreeSet<FSTField>(); final TreeSet<FSTClassFragment> innerClasses = new TreeSet<FSTClassFragment>(); final TreeSet<FSTInvariant> invariants = new TreeSet<FSTInvariant>(); FSTClassFragment innerClassCast = (FSTClassFragment) parentElement; invariants.addAll(innerClassCast.getInvariants()); LinkedList<FSTClassFragment> allFragments = innerClassCast.getRole().getAllEqualFSTFragments(innerClassCast); for (FSTClassFragment fstClassFragment : allFragments) { methods.addAll(fstClassFragment.getMethods()); fields.addAll(fstClassFragment.getFields()); } innerClasses.addAll(innerClassCast.getInnerClasses()); obj = new IRoleElement [methods.size() + fields.size() + invariants.size() + innerClasses.size()]; int pos = 0; System.arraycopy(invariants.toArray(), 0, obj, pos, invariants.size()); System.arraycopy(fields.toArray(), 0, obj, pos += invariants.size(), fields.size()); System.arraycopy(methods.toArray(), 0, obj, pos += fields.size(), methods.size()); System.arraycopy(innerClasses.toArray(), 0, obj, pos += methods.size(), innerClasses.size()); } return filter(obj); }