Package ro.redeul.google.go.inspection

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

package ro.redeul.google.go.inspection;

import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import ro.redeul.google.go.GoBundle;
import ro.redeul.google.go.inspection.fix.DeleteStmtFix;
import ro.redeul.google.go.inspection.fix.constDeclaration.AddMissingConstFix;
import ro.redeul.google.go.inspection.fix.constDeclaration.AddMissingExpressionFix;
import ro.redeul.google.go.inspection.fix.constDeclaration.RemoveRedundantConstFix;
import ro.redeul.google.go.inspection.fix.constDeclaration.RemoveRedundantExpressionFix;
import ro.redeul.google.go.lang.psi.GoFile;
import ro.redeul.google.go.lang.psi.declarations.GoConstDeclaration;
import ro.redeul.google.go.lang.psi.declarations.GoConstDeclarations;
import ro.redeul.google.go.lang.psi.expressions.GoExpr;
import ro.redeul.google.go.lang.psi.expressions.literals.GoLiteralIdentifier;
import ro.redeul.google.go.lang.psi.visitors.GoRecursiveElementVisitor;

public class ConstDeclarationInspection extends AbstractWholeGoFileInspection {

    @Override
    protected void doCheckFile(@NotNull GoFile file,
                               @NotNull final InspectionResult result) {

        new GoRecursiveElementVisitor() {
            @Override
            public void visitConstDeclarations(GoConstDeclarations declarations) {
                checkConstDeclarations(declarations, result);
                visitElement(declarations);
            }

            @Override
            public void visitConstDeclaration(GoConstDeclaration declaration) {
                checkConstDeclaration(declaration, result);
            }
        }.visitFile(file);
    }

    public static void checkConstDeclarations(GoConstDeclarations constDecls,
                                              InspectionResult result) {
        if (isMissingFirstExpressionDeclaration(constDecls)) {
            result.addProblem(constDecls.getDeclarations()[0],
                              GoBundle.message(
                                  "error.missing.first.const.expression"),
                              ProblemHighlightType.ERROR,
                              new AddMissingExpressionFix(),
                              new DeleteStmtFix()
                    );
        }
    }

    public static void checkConstDeclaration(GoConstDeclaration declaration,
                                             InspectionResult results) {

        if (isNoExpressionAndConstCountMismatch(declaration)) {
            results.addProblem(declaration,
                    GoBundle.message(
                            "error.no.expression.const.count.mismatch.in.const.declaration"),
                    ProblemHighlightType.GENERIC_ERROR
                    );
        } else if (isMissingExpressionInConst(declaration)) {
            results.addProblem(declaration,
                    GoBundle.message(
                            "error.missing.expr.for.const.declaration"),
                    ProblemHighlightType.GENERIC_ERROR,
                    new AddMissingExpressionFix(),
                    new RemoveRedundantConstFix()
            );
        } else if (isExtraExpressionInConst(declaration)) {
            results.addProblem(declaration,
                    GoBundle.message(
                            "error.extra.expr.in.const.declaration"),
                    ProblemHighlightType.GENERIC_ERROR,
                    new AddMissingConstFix(),
                    new RemoveRedundantExpressionFix()
            );
        }
    }

    // According to spec:
    // Within a parenthesized const declaration list the expression list may be omitted from any but the first declaration
    private static boolean isMissingFirstExpressionDeclaration(
        GoConstDeclarations constDeclarations)
    {
        GoConstDeclaration[] declarations = constDeclarations.getDeclarations();
        return declarations.length != 0 && declarations[0].getExpressions().length == 0;
    }

    private static boolean isMissingExpressionInConst(GoConstDeclaration declaration) {
        GoLiteralIdentifier[] ids = declaration.getIdentifiers();
        GoExpr[] exprs = declaration.getExpressions();

        return
            declaration.hasInitializers() &&
                ids.length > exprs.length;
    }

    // According to spec:
    // Omitting the list of expressions is therefore equivalent to repeating the previous list.
    // The number of identifiers must be equal to the number of expressions in the previous list
    private static boolean isNoExpressionAndConstCountMismatch(GoConstDeclaration declaration) {
        if (declaration.hasInitializers()) {
            return false;
        }

        PsiElement element = declaration;
        while ((element = element.getPrevSibling()) != null) {
            if (element instanceof GoConstDeclaration) {
                GoConstDeclaration preConst = (GoConstDeclaration) element;
                if (preConst.hasInitializers()) {
                    return declaration.getIdentifiers().length != preConst.getIdentifiers().length;
                }
            }
        }
        return false;
    }

    private static boolean isExtraExpressionInConst(GoConstDeclaration declaration) {
        GoLiteralIdentifier[] ids = declaration.getIdentifiers();
        GoExpr[] exprs = declaration.getExpressions();

        return
            declaration.hasInitializers() &&
                ids.length < exprs.length;
    }
}
TOP

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

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.