Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[xtext-dev] context dependend formatting

It would be nice to have the current AbstractNode in method FormattingConfigBasedStream::addLineEntry available. The grammarElement and the string value isn't enough for context sensitiv formatting. The current workaround looks like a function eg interface in a subclass of FormattingConfigBasedStream

    protected AbstractNode node = null;
    public void setNodeHint(AbstractNode node) {
        this.node = node;
    }

This is called in a function override in a subclass of DefaultNodeModelFormatter, eg

    @Override
    public IFormattedRegion format(CompositeNode root, int offset, int length) {
        List<AbstractNode> nodes = getLeafs(root, offset, offset + length);
        if (nodes.size() == 0)
            return null;

        String indent = getIndentation(root, offset);
        TokenStringBuffer buf = new TokenStringBuffer();
        ITokenStream fmt = formatter.createFormatterStream(indent, buf, false);
       
        // this is xcl
        XclFormattingConfigBasedStream xcl = null;
        if ( fmt instanceof XclFormattingConfigBasedStream )
            xcl = (XclFormattingConfigBasedStream) fmt;

        try {
            for (AbstractNode n : nodes) {
                // this is xcl
                if ( null != xcl)
                    xcl.setNodeHint(n);
                ...

No you can do context sensitive formatting eg leave the linebreaks out for an xml-like grammar just for <i>-tags in the subclass of FormattingConfigBasedStream

    protected boolean cleanNext = false;

    @Override
    protected void addLineEntry(EObject grammarElement, String value,
            boolean isHidden) throws IOException {
        Set<ElementLocator> locators = collectLocators(last, grammarElement);
        // System.out.println(loc + " --> " + value.replaceAll("\n", "\\n"));

        if (cleanNext) {
            locators = normalizeLinebreaks(locators);
            cleanNext = false;
        }

        if (value.equals("<") || value.equals("</")) {
            // we ar on Start or Stop
            if (node.eContainer() instanceof CompositeNode) {
                EObject obj = ((CompositeNode) node.eContainer()).getElement();
                if (obj instanceof Start) {
                    Start start = (Start) obj;
                    if ("em".equals(start.getStart())) {
                         locators = normalizeLinebreaks(locators);
                    }
                } else if (obj instanceof Stop) {
                    Stop stop = (Stop) obj;
                    if ("em".equals(stop.getStop())) {
                        locators = normalizeLinebreaks(locators);
                    }
                }
            }
        } else if (value.equals(">") || value.equals("/>")) {
            // we are on the element
            if (node.eContainer() instanceof CompositeNode) {
                EObject obj = ((CompositeNode) node.eContainer()).getElement();
                if (obj instanceof Start) {
                    Start start = (Start) obj;
                    if ("em".equals(start.getStart())) {
                        cleanNext = true;
                    }
                } else if (obj instanceof Stop) {
                    Stop elem = ((Stop) obj);
                    if ("em".equals(elem.getStop())) {
                        cleanNext = true;
                    }
                }

            }
        }

        last = grammarElement;
        LineEntry e = new LineEntry(grammarElement, value, true, locators,
                preservedWS, indentationLevel);
        preservedWS = null;
        if (currentLine == null)
            currentLine = new Line();
        Line newLine = currentLine.add(e);
        if (newLine != null)
            currentLine = newLine;
    }

    protected Set<ElementLocator> normalizeLinebreaks(
            Set<ElementLocator> locators) {
        Set<ElementLocator> locs = Sets.newHashSet();

        for (ElementLocator elm : locators) {
            if (!(elm instanceof LinewrapLocator
                    || elm instanceof IndentationLocatorStart || elm instanceof IndentationLocatorEnd))
                locs.add(elm);
        }

        return locs;
    }

Having AbstractNode availiable in FormattingConfigBasedStream would do this in a standard way, at the best in a new overrideable function like normalizeCurrent with the content of the bold part.



Back to the top