All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.org.codehaus.janino.util.AutoIndentWriter Maven / Gradle / Ivy

There is a newer version: 5.4.0
Show newest version

/*
 * Janino - An embedded Java[TM] com.hazelcast.com.iler
 *
 * Copyright (c) 2001-2010 Arno Unkrig. All rights reserved.
 * Copyright (c) 2015-2016 TIBCO Software Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
 * following conditions are met:
 *
 *    1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *       following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
 *       following disclaimer in the documentation and/or other materials provided with the distribution.
 *    3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
 *       products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.hazelcast.org.codehaus.janino.util;

import java.io.FilterWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import com.hazelcast.org.codehaus.com.hazelcast.com.ons.nullanalysis.Nullable;

/**
 * A {@link java.io.FilterWriter} that automatically indents lines by looking at trailing opening braces ('{') and
 * leading closing braces ('}').
 */
public
class AutoIndentWriter extends FilterWriter {

    /**
     * Special character indicating a tabular layout of the following text.
     */
    public static final char TABULATOR = 0xffff;

    /**
     * Special character indicating to clear all tabluar layout that was configured through {@link #TABULATOR}.
     */
    public static final char CLEAR_TABULATORS = 0xfffe;

    /**
     * Special character that inserts a line break and indents the following text by one position.
     */
    public static final char INDENT = 0xfffd;

    /**
     * Special character that inserts a line break and unindents the following text by one position.
     */
    public static final char UNINDENT = 0xfffc;

    private final StringBuilder           lineBuffer = new StringBuilder();
    private int                           indentation;
    @Nullable private List tabulatorBuffer;
    private int                           tabulatorIndentation;

    public
    AutoIndentWriter(Writer out) { super(out); }

    @Override public void
    write(@Nullable char[] cbuf, int off, int len) throws IOException {
        assert cbuf != null;
        for (; len > 0; --len) this.write(cbuf[off++]);
    }

    @Override public void
    write(@Nullable String str, int off, int len) throws IOException {
        assert str != null;
        for (; len > 0; --len) this.write(str.charAt(off++));
    }

    @Override public void
    write(int c) throws IOException {
        if (c == '\n') {
            this.lineBuffer.append('\n');
            this.line(this.lineBuffer.toString());
            this.lineBuffer.setLength(0);
            return;
        }
        if (this.lineBuffer.length() > 0 && this.lineBuffer.charAt(this.lineBuffer.length() - 1) == '\r') {
            this.line(this.lineBuffer.toString());
            this.lineBuffer.setCharAt(0, (char) c);
            this.lineBuffer.setLength(1);
            return;
        }
        this.lineBuffer.append((char) c);
    }

    private void
    line(String line) throws IOException {
        if (this.tabulatorBuffer != null) {
            this.tabulatorBuffer.add(new StringBuilder(line.length()).append(line));
            if (line.charAt(0) == AutoIndentWriter.INDENT) { ++this.indentation; line = line.substring(1); }
            if (line.charAt(0) == AutoIndentWriter.UNINDENT && --this.indentation < this.tabulatorIndentation) {
                this.flushTabulatorBuffer();
            }
        } else
        if (line.indexOf(AutoIndentWriter.TABULATOR) != -1) {
            if (line.charAt(0) == AutoIndentWriter.INDENT)   { ++this.indentation; line = line.substring(1); }
            if (line.charAt(0) == AutoIndentWriter.UNINDENT) { --this.indentation; line = line.substring(1); }

            this.tabulatorBuffer = new ArrayList();
            this.tabulatorBuffer.add(new StringBuilder(line.length()).append(line));
            this.tabulatorIndentation = this.indentation;
        } else
        {
            if (line.charAt(0) == AutoIndentWriter.CLEAR_TABULATORS) line = line.substring(1);
            if (line.charAt(0) == AutoIndentWriter.INDENT)           { ++this.indentation; line = line.substring(1); }
            if (line.charAt(0) == AutoIndentWriter.UNINDENT)         { --this.indentation; line = line.substring(1); }
            if ("\r\n".indexOf(line.charAt(0)) == -1) {
                for (int i = 0; i < this.indentation; ++i) this.out.write("    ");
            }
            this.out.write(line);
        }
    }

    private void
    flushTabulatorBuffer() throws IOException {
        List> lineGroups = new ArrayList>();
        lineGroups.add(new ArrayList());

        List tb = this.tabulatorBuffer;
        assert tb != null;
        for (StringBuilder line : tb) {

            int idx = 0;
            if (line.charAt(0) == AutoIndentWriter.INDENT) {
                lineGroups.add(new ArrayList());
                ++idx;
            }
            if (line.charAt(idx) == AutoIndentWriter.UNINDENT) {
                AutoIndentWriter.resolveTabs(lineGroups.remove(lineGroups.size() - 1));
                ++idx;
            }
            if (line.charAt(idx) == AutoIndentWriter.CLEAR_TABULATORS) {
                List lg = lineGroups.get(lineGroups.size() - 1);
                AutoIndentWriter.resolveTabs(lg);
                lg.clear();
                line.deleteCharAt(idx);
            }
            for (int i = 0; i < line.length(); ++i) {
                if (line.charAt(i) == AutoIndentWriter.TABULATOR) {
                    ((List) lineGroups.get(lineGroups.size() - 1)).add(line);
                }
            }
        }
        for (List lg : lineGroups) AutoIndentWriter.resolveTabs(lg);
        int ind = this.tabulatorIndentation;
        for (StringBuilder sb : tb) {
            String line = sb.toString();
            if (line.charAt(0) == AutoIndentWriter.INDENT) {
                ++ind;
                line = line.substring(1);
            }
            if (line.charAt(0) == AutoIndentWriter.UNINDENT) {
                --ind;
                line = line.substring(1);
            }
            if ("\r\n".indexOf(line.charAt(0)) == -1) {
                for (int i = 0; i < ind; ++i) this.out.write("    ");
            }
            this.out.write(line.toString());
        }
        this.tabulatorBuffer = null;
    }

    /**
     * Expands all {@link #TABULATOR}s in the given {@link List} of {@link StringBuilder}s with
     * spaces, so that the characters immediately following the {@link #TABULATOR}s are vertically
     * aligned, like this:
     * 

* Input: *

*
     *   a @b @c\r\n
     *   aa @bb @cc\r\n
     *   aaa @bbb @ccc\r\n
     * 
*

* Output: *

*
     *   a   b   c\r\n
     *   aa  bb  cc\r\n
     *   aaa bbb ccc\r\n
     * 
*/ private static void resolveTabs(List lineGroup) { // Determine the tabulator offsets for this line group. List tabulatorOffsets = new ArrayList(); // 4, 4 for (StringBuilder line : lineGroup) { int previousTab = 0; if (line.charAt(previousTab) == AutoIndentWriter.INDENT) ++previousTab; if (line.charAt(previousTab) == AutoIndentWriter.UNINDENT) ++previousTab; int tabCount = 0; for (int i = previousTab; i < line.length(); ++i) { if (line.charAt(i) == AutoIndentWriter.TABULATOR) { int tabOffset = i - previousTab; previousTab = i; if (tabCount >= tabulatorOffsets.size()) { tabulatorOffsets.add(new Integer(tabOffset)); } else { if (tabOffset > ((Integer) tabulatorOffsets.get(tabCount)).intValue()) { tabulatorOffsets.set(tabCount, new Integer(tabOffset)); } } ++tabCount; } } } // Replace tabulators with spaces. for (Iterator it = lineGroup.iterator(); it.hasNext();) { StringBuilder line = (StringBuilder) it.next(); int tabCount = 0; int previousTab = 0; if (line.charAt(previousTab) == AutoIndentWriter.INDENT) ++previousTab; if (line.charAt(previousTab) == AutoIndentWriter.UNINDENT) ++previousTab; for (int i = previousTab; i < line.length(); ++i) { if (line.charAt(i) == AutoIndentWriter.TABULATOR) { int tabOffset = i - previousTab; int n = ((Integer) tabulatorOffsets.get(tabCount++)).intValue() - tabOffset; line.replace(i, i + 1, AutoIndentWriter.spaces(n)); i += n - 1; previousTab = i; } } } } /** * @return a {@link String} of {@code n} spaces */ private static String spaces(int n) { if (n < 30) return " ".substring(0, n); char[] data = new char[n]; Arrays.fill(data, ' '); return String.valueOf(data); } @Override public void close() throws IOException { if (this.tabulatorBuffer != null) this.flushTabulatorBuffer(); if (this.lineBuffer.length() > 0) this.line(this.lineBuffer.toString()); this.out.close(); } @Override public void flush() throws IOException { if (this.tabulatorBuffer != null) this.flushTabulatorBuffer(); if (this.lineBuffer.length() > 0) { this.line(this.lineBuffer.toString()); this.lineBuffer.setLength(0); } this.out.flush(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy