Package ro.redeul.google.go.intentions.conversions

Source Code of ro.redeul.google.go.intentions.conversions.ConvertSwitchToIfIntention$SwitchElements

package ro.redeul.google.go.intentions.conversions;

import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import ro.redeul.google.go.intentions.GoIntentionsBundle;
import ro.redeul.google.go.intentions.Intention;
import ro.redeul.google.go.intentions.IntentionExecutionException;
import ro.redeul.google.go.lang.documentation.DocumentUtil;
import ro.redeul.google.go.lang.lexer.GoTokenTypes;
import ro.redeul.google.go.lang.parser.GoElementTypes;
import ro.redeul.google.go.lang.psi.expressions.GoExpr;
import ro.redeul.google.go.lang.psi.statements.GoSimpleStatement;
import ro.redeul.google.go.lang.psi.statements.GoStatement;
import ro.redeul.google.go.lang.psi.statements.switches.GoSwitchExpressionClause;
import ro.redeul.google.go.lang.psi.statements.switches.GoSwitchExpressionStatement;
import ro.redeul.google.go.util.expression.FlipBooleanExpression;

import java.util.ArrayList;
import java.util.List;

import static ro.redeul.google.go.lang.psi.utils.GoPsiUtils.*;
import static ro.redeul.google.go.util.EditorUtil.reformatPositions;

public class ConvertSwitchToIfIntention extends Intention {
    @Override
    protected boolean satisfiedBy(PsiElement element) {
        return isNodeOfType(element, GoTokenTypes.kSWITCH) &&
               isNodeOfType(element.getParent(), GoElementTypes.SWITCH_EXPR_STATEMENT);
    }

    @Override
    protected void processIntention(@NotNull PsiElement element, Editor editor)
            throws IntentionExecutionException {
        GoSwitchExpressionStatement se = findParentOfType(element, GoSwitchExpressionStatement.class);
        if (se == null) {
            return;
        }

        checkFallthrough(se);

        Document document = editor.getDocument();
        RangeMarker range = document.createRangeMarker(se.getTextRange());
        SwitchElements switchElements = SwitchElements.create(document, se);
        DocumentUtil.replaceElementWithText(document, se, switchElements.toIf());
        reformatPositions(se.getContainingFile(), range);
    }

    private void checkFallthrough(GoSwitchExpressionStatement se) {
        for (GoSwitchExpressionClause clause : se.getClauses()) {
            GoStatement[] statements = clause.getStatements();
            if (statements.length == 0) {
                continue;
            }

            GoStatement lastStatement = statements[statements.length - 1];
            if (isNodeOfType(lastStatement, GoElementTypes.FALLTHROUGH_STATEMENT)) {
                int start = lastStatement.getTextOffset() - se.getTextOffset();
                String msg = GoIntentionsBundle.message("error.refuse.to.convert.fallthrough");
                throw new IntentionExecutionException(msg, start, lastStatement.getTextLength());
            }
        }
    }

    private static class SwitchElements {
        public final String simpleStatement;
        public final String expression;
        public final List<CaseElement> cases;
        public final CaseElement defaultElement;

        private SwitchElements(String simpleStatement, String expression, List<CaseElement> cases,
                               CaseElement defaultElement) {
            this.simpleStatement = simpleStatement;
            this.expression = expression;
            this.cases = cases;
            this.defaultElement = defaultElement;
        }

        private String toIf() {
            StringBuilder sb = new StringBuilder("if ");
            if (!simpleStatement.isEmpty()) {
                sb.append(simpleStatement).append("; ");
            }

            for (int i = 0; i < cases.size(); i++) {
                if (i > 0) {
                    sb.append(" else if ");
                }
                CaseElement c = cases.get(i);
                sb.append(c.getCondition(expression)).append(" {\n").append(c.statements).append("\n}");
            }

            if (cases.isEmpty()) {
                sb.append("false {\n}");
            }

            if (defaultElement != null) {
                sb.append(" else {\n").append(defaultElement.statements).append("\n}");
            }
            return sb.toString();
        }

        private static SwitchElements create(Document document, GoSwitchExpressionStatement se) {
            GoSimpleStatement simpleStatement = se.getSimpleStatement();
            String ss = simpleStatement == null ? "" : simpleStatement.getText();
            GoExpr expression = se.getExpression();
            boolean expressionIsTrue = expression == null || "true".equals(expression.getText());
            boolean expressionIsFalse = expression != null && "false".equals(expression.getText());
            String es = expressionIsTrue || expressionIsFalse ? "" : expression.getText();
            CaseElement defaultCase = null;
            List<CaseElement> cases = new ArrayList<CaseElement>();
            for (GoSwitchExpressionClause clause : se.getClauses()) {
                CaseElement c = CaseElement.create(document, clause, expressionIsFalse);
                if (clause.isDefault()) {
                    defaultCase = c;
                } else if (c != null) {
                    cases.add(c);
                }
            }
            return new SwitchElements(ss, es, cases, defaultCase);
        }
    }

    private static class CaseElement {
        public final List<String> expressions;
        public final String statements;

        private CaseElement(List<String> expressions, String statements) {
            this.expressions = expressions;
            this.statements = statements;
        }

        private String getCondition(String e) {
            StringBuilder sb = new StringBuilder();
            for (String expr : expressions) {
                if (sb.length() > 0) {
                    sb.append(" || ");
                }
                if (e.isEmpty()) {
                    sb.append(expr);
                } else {
                    sb.append(e).append(" == ").append(expr);
                }
            }
            return sb.toString();
        }

        private static CaseElement create(Document document, GoSwitchExpressionClause clause, boolean flipExpression) {
            List<String> expressions = new ArrayList<String>();
            for (GoExpr expr : clause.getExpressions()) {
                expressions.add(flipExpression ? FlipBooleanExpression.flip(expr) : expr.getText());
            }
            PsiElement colon = findChildOfType(clause, GoTokenTypes.oCOLON);
            if (colon == null) {
                return null;
            }

            int start = colon.getTextOffset() + 1;
            int end = clause.getTextRange().getEndOffset();
            String statements = document.getText(TextRange.create(start, end)).trim();
            return new CaseElement(expressions, statements);
        }
    }
}
TOP

Related Classes of ro.redeul.google.go.intentions.conversions.ConvertSwitchToIfIntention$SwitchElements

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.