Package ro.redeul.google.go.inspection

Source Code of ro.redeul.google.go.inspection.FunctionWithResultButWihtoutReturnInspection

package ro.redeul.google.go.inspection;

import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import ro.redeul.google.go.GoBundle;
import ro.redeul.google.go.inspection.fix.AddReturnStmtFix;
import ro.redeul.google.go.inspection.fix.RemoveFunctionResultFix;
import ro.redeul.google.go.lang.psi.GoFile;
import ro.redeul.google.go.lang.psi.expressions.GoPrimaryExpression;
import ro.redeul.google.go.lang.psi.expressions.literals.GoLiteralFunction;
import ro.redeul.google.go.lang.psi.expressions.primary.GoBuiltinCallOrConversionExpression;
import ro.redeul.google.go.lang.psi.statements.*;
import ro.redeul.google.go.lang.psi.statements.select.GoSelectCommClause;
import ro.redeul.google.go.lang.psi.statements.select.GoSelectStatement;
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.lang.psi.statements.switches.GoSwitchTypeClause;
import ro.redeul.google.go.lang.psi.statements.switches.GoSwitchTypeStatement;
import ro.redeul.google.go.lang.psi.toplevel.GoFunctionDeclaration;
import ro.redeul.google.go.lang.psi.toplevel.GoMethodDeclaration;
import ro.redeul.google.go.lang.psi.visitors.GoRecursiveElementVisitor;

public class FunctionWithResultButWihtoutReturnInspection extends AbstractWholeGoFileInspection
{
    @Override
    protected void doCheckFile(@NotNull GoFile file, @NotNull final InspectionResult result) {

        new GoRecursiveElementVisitor() {
            @Override
            public void visitFunctionDeclaration(GoFunctionDeclaration declaration) {
                checkFunction(result, declaration);
            }

            @Override
            public void visitMethodDeclaration(GoMethodDeclaration declaration) {
                checkFunction(result, declaration);
            }

            @Override
            public void visitFunctionLiteral(GoLiteralFunction literal) {
                checkFunction(result, literal);
            }
        }.visitFile(file);
    }

    public static void checkFunction(InspectionResult result, GoFunctionDeclaration function) {
        hasResultButNoReturnAtTheEnd(result, function);
    }

    private static void hasResultButNoReturnAtTheEnd(InspectionResult result, GoFunctionDeclaration function) {
        if (hasResult(function) && hasBody(function) && !hasReturnAtTheEnd(function)) {
            LocalQuickFix fix1 = new AddReturnStmtFix(function);
            LocalQuickFix fix2 = new RemoveFunctionResultFix(function);
            PsiElement element = function.getBlock().getLastChild();
            result.addProblem(element, GoBundle.message("error.no.return.found"), fix1, fix2);
        }
    }

    private static boolean hasResult(GoFunctionDeclaration function) {
        return function.getResults().length > 0;
    }

    private static boolean hasBody(GoFunctionDeclaration function) {
        return function.getBlock() != null;
    }

    private static boolean hasReturnAtTheEnd(GoFunctionDeclaration function) {
        return isTerminating(function.getBlock());
    }

    private static boolean isPanicCall(PsiElement element) {
        if (!(element instanceof GoExpressionStatement)) {
            return false;
        }

        PsiElement call = element.getFirstChild();
        if (!(call instanceof GoBuiltinCallOrConversionExpression)) {
            return false;
        }

        GoPrimaryExpression expression = ((GoBuiltinCallOrConversionExpression) call).getBaseExpression();
        return expression != null && "panic".equals(expression.getText());
    }

    private static boolean isTerminating(GoStatement statement) {
        if (statement instanceof GoReturnStatement) {
            return true;
        }else if (statement instanceof GoGoStatement){
            return true;
        }else if (isPanicCall(statement)) {
            return true;
        }else if (statement instanceof GoBlockStatement) {
            GoBlockStatement block = (GoBlockStatement)statement;
            GoStatement[] statements = block.getStatements();
            return statements.length > 0 && isTerminating(statements[statements.length - 1]);
        }else if (statement instanceof GoIfStatement) {
            GoIfStatement ifStatement = (GoIfStatement)(statement);
            if (!isTerminating(ifStatement.getThenBlock())){
                return false;
            }else if (ifStatement.getElseIfStatement() != null){
                return isTerminating(ifStatement.getElseIfStatement());
            }else if (ifStatement.getElseBlock() != null) {
                return isTerminating(ifStatement.getElseBlock());
            }else {
                return false;
            }
        }else if(statement instanceof GoForWithConditionStatement){
            GoForWithConditionStatement forStatement = (GoForWithConditionStatement)statement;
            return forStatement.getCondition() == null;
        }else if(statement instanceof GoForWithClausesStatement){
            GoForWithClausesStatement forStatement = (GoForWithClausesStatement)statement;
            return forStatement.getCondition() == null;
        }else if (statement instanceof GoSwitchExpressionStatement){
            GoSwitchExpressionStatement switchExpr = (GoSwitchExpressionStatement)statement;
            boolean hasDefalut = false;
            for (GoSwitchExpressionClause clause: switchExpr.getClauses()) {
                if (clause.isDefault()) {
                    hasDefalut = true;
                }
                GoStatement[] statmentsInClause = clause.getStatements();

                if (statmentsInClause.length == 0) {
                    return false;
                }

                if (!isTerminating(statmentsInClause[statmentsInClause.length-1])){
                    return false;
                }
            }
            return hasDefalut;
        }else if (statement instanceof GoSwitchTypeStatement){
            GoSwitchTypeStatement switchTypeStatement = (GoSwitchTypeStatement)statement;
            boolean hasDefalut = false;
            for (GoSwitchTypeClause clause: switchTypeStatement.getClauses()) {
                if (clause.isDefault()) {
                    hasDefalut = true;
                }
                GoStatement[] statmentsInClause = clause.getStatements();

                if (statmentsInClause.length == 0) {
                    return false;
                }

                if (!isTerminating(statmentsInClause[statmentsInClause.length-1])){
                    return false;
                }
            }
            return hasDefalut;
        }else if (statement instanceof GoSelectStatement){
            GoSelectStatement selectStatement = (GoSelectStatement)statement;
            for (GoSelectCommClause clause : selectStatement.getCommClauses()) {
                GoStatement[] statmentsInClause = clause.getStatements();
                if (statmentsInClause.length == 0) {
                    return false;
                }
                if (!isTerminating(statmentsInClause[statmentsInClause.length-1])){
                    return false;
                }
            }
            return true;
        }else if (statement instanceof GoLabeledStatement){
            GoLabeledStatement labeledStatement = (GoLabeledStatement)statement;
            return isTerminating (labeledStatement.getStatement());
        }else{
            return false;
        }
    }

}
TOP

Related Classes of ro.redeul.google.go.inspection.FunctionWithResultButWihtoutReturnInspection

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.