private void addFolds( BaseDocument doc, List<? extends ASTElement> elements, Map<String, List<OffsetRange>> folds, List<OffsetRange> codeblocks) throws BadLocationException { for (ASTElement element : elements) { ElementKind kind = element.getKind(); switch (kind) { case FIELD: case METHOD: case CONSTRUCTOR: case CLASS: case MODULE: ASTNode node = element.getNode(); OffsetRange range = ASTUtils.getRangeFull(node, doc); // beware of synthetic elements if ((kind == ElementKind.METHOD && !((MethodNode) node).isSynthetic()) || (kind == ElementKind.CONSTRUCTOR && !((ConstructorNode) node).isSynthetic()) || (kind == ElementKind.FIELD && ((FieldNode) node).getInitialExpression() instanceof ClosureExpression) // Only make nested classes/modules foldable, similar to what the java editor is doing || (range.getStart() > Utilities.getRowStart(doc, range.getStart())) && kind != ElementKind.FIELD) { int start = range.getStart(); // Start the fold at the END of the line behind last non-whitespace, remove curly brace, // if any start = Utilities.getRowLastNonWhite(doc, start); if (start >= 0 && doc.getChars(start, 1)[0] != '{') { start++; } int end = range.getEnd(); if (start != (-1) && end != (-1) && start < end && end <= doc.getLength()) { range = new OffsetRange(start, end); codeblocks.add(range); } } break; } List<? extends ASTElement> children = element.getChildren(); if (children != null && children.size() > 0) { addFolds(doc, children, folds, codeblocks); } } }
@Override public String getHtml(HtmlFormatter formatter) { formatter.appendText(node.getName()); if ((kind == ElementKind.METHOD) || (kind == ElementKind.CONSTRUCTOR)) { // Append parameters ASTMethod jn = (ASTMethod) node; Collection<String> parameters = jn.getParameters(); if ((parameters != null) && (parameters.size() > 0)) { formatter.appendHtml("("); formatter.parameters(true); for (Iterator<String> it = parameters.iterator(); it.hasNext(); ) { String ve = it.next(); // TODO - if I know types, list the type here instead. For now, just use the parameter // name instead formatter.appendText(ve); if (it.hasNext()) { formatter.appendHtml(", "); } } formatter.parameters(false); formatter.appendHtml(")"); } else { formatter.appendHtml("()"); } } return formatter.getText(); }
private GroovyStructureItem(ASTElement node, ParserResult info) { this.node = node; this.kind = node.getKind(); this.info = info; // FIXME true or false ? this.doc = (BaseDocument) info.getSnapshot().getSource().getDocument(false); }
@Override public long getEndPosition() { if (doc != null) { OffsetRange range = ASTUtils.getRangeFull(node.getNode(), doc); LOG.log(Level.FINEST, "getEndPosition(), end: {0}", range.getEnd()); return (long) range.getEnd(); } return 0; }
private static boolean isVisible(ASTElement element) { // FIXME perhaps we should store synthetic atributte in AstElement if ((element.getKind() == ElementKind.METHOD)) { ASTMethod method = (ASTMethod) element; ASTNode node = method.getNode(); return !(node instanceof MethodNode) || (!((MethodNode) node).isSynthetic() && ((MethodNode) node).getLineNumber() >= 0); } return true; }
@Override public List<? extends StructureItem> getNestedItems() { List<ASTElement> nested = node.getChildren(); if ((nested != null) && (nested.size() > 0)) { List<GroovyStructureItem> children = new ArrayList<GroovyStructureItem>(nested.size()); // FIXME: the same old problem: AstElement != ElementHandle. for (ASTElement co : nested) { if (isVisible(co)) { children.add(new GroovyStructureItem(co, info)); } } return children; } else { return Collections.emptyList(); } }
@Override public Set<Modifier> getModifiers() { return node.getModifiers(); }
@Override public String getName() { return node.getName(); }
private void scan( GroovyParserResult result, ASTNode node, AstPath path, String in, Set<String> includes, ASTElement parent) { if (node instanceof AnnotatedNode && !((AnnotatedNode) node).hasNoRealSourcePosition()) { if (node instanceof ClassNode) { ASTClass co = new ASTClass(result, node); co.setFqn(((ClassNode) node).getName()); if (parent != null) { parent.addChild(co); } else { structure.add(co); } parent = co; } else if (node instanceof FieldNode) { if (parent instanceof ASTClass) { // We don't have unique declarations, only assignments (possibly many) // so stash these in a map and extract unique fields when we're done Set<FieldNode> assignments = fields.get(parent); if (assignments == null) { assignments = new HashSet<FieldNode>(); fields.put((ASTClass) parent, assignments); } assignments.add((FieldNode) node); } } else if (node instanceof MethodNode) { ASTMethod co = new ASTMethod(result, node); methods.add(co); co.setIn(in); // TODO - don't add this to the top level! Make a nested list if (parent != null) { parent.addChild(co); } else { structure.add(co); } } else if (node instanceof PropertyNode) { Set<PropertyNode> declarations = properties.get(parent); if (declarations == null) { declarations = new HashSet<PropertyNode>(); properties.put((ASTClass) parent, declarations); } declarations.add((PropertyNode) node); } } @SuppressWarnings("unchecked") List<ASTNode> list = ASTUtils.children(node); for (ASTNode child : list) { path.descend(child); scan(result, child, path, in, includes, parent); path.ascend(); } }