Package info.cukes.editor.formatting

Source Code of info.cukes.editor.formatting.CucumberFormatter

package info.cukes.editor.formatting;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.TypedPosition;
import org.eclipse.jface.text.formatter.FormattingContextProperties;
import org.eclipse.jface.text.formatter.IFormattingContext;
import org.eclipse.jface.text.formatter.IFormattingStrategy;
import org.eclipse.jface.text.formatter.IFormattingStrategyExtension;
import org.eclipse.text.edits.DeleteEdit;
import org.eclipse.text.edits.InsertEdit;
import org.eclipse.text.edits.MultiTextEdit;

public class CucumberFormatter implements IFormattingStrategy, IFormattingStrategyExtension {
    private static final String SPACE = "    ";

    private IFormattingContext context;
    private String lineDelimiter;
    private String originalString;
    private Set<String> annotations = new HashSet<String>();

    public CucumberFormatter() {
        annotations.add("Given ");
        annotations.add("And ");
        annotations.add("But ");
        annotations.add("When ");
        annotations.add("Then ");
    }

    @Override
    public void formatterStarts(String initialIndentation) {
        // TODO Auto-generated method stub
    }

    @Override
    public String format(String content, boolean isLineStart, String indentation, int[] positions) {
        return null;
    }

    @Override
    public void formatterStops() {
        this.context = null;
    }

    @Override
    public void format() {
        final IDocument document = (IDocument) context.getProperty(FormattingContextProperties.CONTEXT_MEDIUM);
        final TypedPosition partition = (TypedPosition) context
            .getProperty(FormattingContextProperties.CONTEXT_PARTITION);

        try {
            originalString = document.get(partition.getOffset(), partition.getLength());
            lineDelimiter = TextUtilities.getDefaultLineDelimiter(document);

            MultiTextEdit allEdits = new MultiTextEdit();

            if (partition.getType().equals(IDocument.DEFAULT_CONTENT_TYPE)) {
                formatFeature(allEdits);
                formatScenarios(allEdits);
                formatAnnotations(allEdits);
                formatGrids(allEdits);
            } else {
                // allEdits.addChild(new InsertEdit(partition.getOffset() + partition.getLength(), lineDelimiter));
            }

            allEdits.apply(document);
        } catch (BadLocationException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void formatterStarts(IFormattingContext context) {
        this.context = context;
    }

    private void formatFeature(MultiTextEdit allEdits) throws BadLocationException {
        int featureIndex = originalString.indexOf("Feature:");
        int lastValidChar = indexOfPreviousChar(originalString, featureIndex);

        if (featureIndex > lastValidChar && lastValidChar >= 0) {
            allEdits.addChild(new DeleteEdit(lastValidChar, featureIndex - lastValidChar));
        }
    }

    private void formatScenarios(MultiTextEdit allEdits) throws BadLocationException {
        int lastIndex = -1;
        int scenarioIndex = -1;
        while ((scenarioIndex = originalString.indexOf("Scenario:", lastIndex + 1)) > -1) {
            lastIndex = scenarioIndex;
            int lastValidChar = indexOfPreviousChar(originalString, scenarioIndex);

            if (scenarioIndex > lastValidChar && lastValidChar >= 0) {
                allEdits.addChild(new DeleteEdit(lastValidChar, scenarioIndex - lastValidChar));
                allEdits.addChild(new InsertEdit(lastValidChar, SPACE));
            }
        }
    }

    private void formatAnnotations(MultiTextEdit allEdits) throws BadLocationException {
        for (String annotation : annotations) {
            int lastIndex = -1;
            int index = -1;
            while ((index = originalString.indexOf(annotation, lastIndex + 1)) > -1) {
                lastIndex = index;
                int lastValidChar = indexOfPreviousChar(originalString, index);

                if (index > lastValidChar && lastValidChar >= 0) {
                    allEdits.addChild(new DeleteEdit(lastValidChar, index - lastValidChar));
                }
                allEdits.addChild(new InsertEdit(lastValidChar, SPACE + SPACE));
            }
        }
    }

    private void formatGrids(MultiTextEdit allEdits) throws BadLocationException {
        String[] lines = originalString.split(lineDelimiter);

        List<String> foundGridLines = new ArrayList<String>();

        for (String line : lines) {
            for (int i = 0; i < line.length(); ++i) {
                char charAt = line.charAt(i);
                if (!Character.isWhitespace(charAt)) {
                    if (charAt == '|') {
                        foundGridLines.add(line);
                    } else {
                        processSingleGrid(allEdits, foundGridLines);
                    }
                    break;
                }
            }
        }

        processSingleGrid(allEdits, foundGridLines);
    }

    private void processSingleGrid(MultiTextEdit allEdits, List<String> foundGridLines) throws BadLocationException {
        Map<Integer, Integer> columnNumberToMaxWidth = new HashMap<Integer, Integer>();

        if (foundGridLines.isEmpty()) {
            return;
        }

        int gridStartIndex = originalString.indexOf(foundGridLines.get(0));

        // Find max column width, issue delete instruction for entire line
        for (String line : foundGridLines) {
            String[] columns = line.split("\\|");
            for (int i = 0; i < columns.length; ++i) {
                Integer currentMax = columnNumberToMaxWidth.get(i);
                if (currentMax == null) {
                    currentMax = -1;
                }

                int columnSize = columns[i].trim().length();
                if (columnSize > currentMax) {
                    columnNumberToMaxWidth.put(i, columnSize);
                }
            }

            allEdits.addChild(new DeleteEdit(originalString.indexOf(line), line.length()));
        }

        // Rebuild entire line from scratch with proper spacing
        StringBuilder formattedGrid = new StringBuilder();
        for (String line : foundGridLines) {
            String[] columns = line.split("\\|");
            formattedGrid.append(SPACE).append(SPACE).append(SPACE);
            for (int i = 0; i < columns.length; ++i) {
                int maxWidth = columnNumberToMaxWidth.get(i);
                if (maxWidth == 0) {
                    continue;
                }

                formattedGrid.append("| ");

                String text = columns[i].trim();

                boolean isNumber = true;
                try {
                    new BigDecimal(text);
                } catch (Exception e) {
                    isNumber = false;
                }

                while (text.length() < maxWidth) {
                    if (isNumber) {
                        text = " " + text;
                    } else {
                        text = text + " ";
                    }
                }

                formattedGrid.append(text).append(" ");
            }
            formattedGrid.append("|").append(lineDelimiter);
        }

        allEdits.addChild(new InsertEdit(gridStartIndex, formattedGrid.toString()));

        foundGridLines.clear();
    }

    private int indexOfPreviousChar(String docAsString, int currentOffset) {
        int lastValidCharIndex = currentOffset - 1;

        while (lastValidCharIndex >= 0) {
            char charAt = originalString.charAt(lastValidCharIndex);
            if (!Character.isWhitespace(charAt)) {
                break;
            }

            lastValidCharIndex--;
        }
        lastValidCharIndex++;
        if (lastValidCharIndex != 0) {
            lastValidCharIndex += lineDelimiter.length();
        }

        return lastValidCharIndex;
    }
}
TOP

Related Classes of info.cukes.editor.formatting.CucumberFormatter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.