Package ro.redeul.google.go.inspection

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

package ro.redeul.google.go.inspection;

import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import ro.redeul.google.go.GoBundle;
import ro.redeul.google.go.lang.psi.GoFile;
import ro.redeul.google.go.lang.psi.GoPsiElement;
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.declarations.GoVarDeclaration;
import ro.redeul.google.go.lang.psi.declarations.GoVarDeclarations;
import ro.redeul.google.go.lang.psi.expressions.literals.GoLiteralFunction;
import ro.redeul.google.go.lang.psi.expressions.literals.GoLiteralIdentifier;
import ro.redeul.google.go.lang.psi.statements.*;
import ro.redeul.google.go.lang.psi.statements.select.GoSelectCommClauseDefault;
import ro.redeul.google.go.lang.psi.statements.select.GoSelectCommClauseRecv;
import ro.redeul.google.go.lang.psi.statements.select.GoSelectCommClauseSend;
import ro.redeul.google.go.lang.psi.statements.select.GoSelectStatement;
import ro.redeul.google.go.lang.psi.statements.switches.*;
import ro.redeul.google.go.lang.psi.toplevel.*;
import ro.redeul.google.go.lang.psi.types.GoPsiTypeInterface;
import ro.redeul.google.go.lang.psi.visitors.GoRecursiveElementVisitor;
import ro.redeul.google.go.lang.stubs.GoNamesCache;

import java.util.Collection;
import java.util.HashSet;
import java.util.Stack;

/**
* find redeclare compiler error.
*/
public class RedeclareInspection extends AbstractWholeGoFileInspection {
    @Override
    protected void doCheckFile(@NotNull GoFile file, @NotNull final InspectionResult result) {
        new GoRecursiveElementVisitor() {
            private Stack<HashSet<String>> blockNameStack = new Stack<HashSet<String>>();
            private HashSet<String> methodNameSet = new HashSet<String>();

            @Override
            public void visitFile(GoFile file) {
                blockNameStack.push(new HashSet<String>());
                methodNameSet = new HashSet<String>();
                //add names from other files in this package.
                Collection<GoFile> packageFiles = GoNamesCache.getInstance(file.getProject()).getFilesByPackageImportPath(file.getFullPackageName());
                for (GoFile file1 : packageFiles) {
                    if (file1 == file) {
                        continue;
                    }
                    for (GoFunctionDeclaration declaration : file1.getFunctions()) {
                        blockNameStack.peek().add(declaration.getName());
                    }
                    for (GoVarDeclarations declarations : file1.getGlobalVariables()) {
                        for (GoVarDeclaration declaration : declarations.getDeclarations()) {
                            for (GoLiteralIdentifier id : declaration.getIdentifiers()) {
                                blockNameStack.peek().add(id.getName());
                            }
                        }
                    }
                    for (GoConstDeclarations declarations : file1.getConsts()) {
                        for (GoConstDeclaration declaration : declarations.getDeclarations()) {
                            for (GoLiteralIdentifier id : declaration.getIdentifiers()) {
                                blockNameStack.peek().add(id.getName());
                            }
                        }
                    }
                    for (GoTypeDeclaration declaration : file1.getTypeDeclarations()) {
                        for (GoTypeSpec spec : declaration.getTypeSpecs()) {
                            GoTypeNameDeclaration names = spec.getTypeNameDeclaration();
                            if (names == null) {
                                continue;
                            }
                            blockNameStack.peek().add(names.getName());
                        }
                    }
                    for (GoMethodDeclaration declaration : file1.getMethods()) {
                        if (declaration.getMethodReceiver() == null ||
                                declaration.getMethodReceiver().getType() == null) {
                            return;
                        }
                        String name = declaration.getMethodReceiver().getType().getText() + "." + declaration.getName();
                        if (name.startsWith("*")) {
                            name = name.substring(1);
                        }
                        methodNameSet.add(name);
                    }
                }
                visitElement(file);
                blockNameStack.pop();
            }

            @Override
            public void visitIfStatement(GoIfStatement element) { visitSampleBlock(element); }

            @Override
            public void visitForWithRange(GoForWithRangeStatement element) { visitSampleBlock(element); }

            @Override
            public void visitForWithRangeAndVars(GoForWithRangeAndVarsStatement element) { visitSampleBlock(element); }

            @Override
            public void visitForWithClauses(GoForWithClausesStatement element) { visitSampleBlock(element); }

            @Override
            public void visitInterfaceType(GoPsiTypeInterface element) { visitSampleBlock(element); }

            @Override
            public void visitSwitchExpressionClause(GoSwitchExpressionClause element) { visitSampleBlock(element); }

            @Override
            public void visitSwitchTypeClause(GoSwitchTypeClause element) { visitSampleBlock(element); }

            @Override
            public void visitSwitchExpressionStatement(GoSwitchExpressionStatement element) { visitSampleBlock(element); }

            @Override
            public void visitSwitchTypeGuard(GoSwitchTypeGuard element) { visitSampleBlock(element); }

            @Override
            public void visitSwitchTypeStatement(GoSwitchTypeStatement element) { visitSampleBlock(element); }

            @Override
            public void visitSelectStatement(GoSelectStatement element) { visitSampleBlock(element); }

            @Override
            public void visitSelectCommClauseDefault(GoSelectCommClauseDefault element) { visitSampleBlock(element); }

            @Override
            public void visitSelectCommClauseRecv(GoSelectCommClauseRecv element) { visitSampleBlock(element); }

            @Override
            public void visitSelectCommClauseSend(GoSelectCommClauseSend element) { visitSampleBlock(element); }

            @Override
            public void visitBlockStatement(GoBlockStatement statement) {
                if (statement.getParent() instanceof GoFunctionDeclaration) {
                    visitElement(statement);
                } else {
                    visitSampleBlock(statement);
                }
            }

            private void visitSampleBlock(GoPsiElement element) {
                blockNameStack.push(new HashSet<String>());
                visitElement(element);
                blockNameStack.pop();
            }

            @Override
            public void visitMethodDeclaration(GoMethodDeclaration declaration) {
                if (declaration.getMethodReceiver() == null ||
                        declaration.getMethodReceiver().getType() == null) {
                    visitElement(declaration);
                    return;
                }
                blockNameStack.push(new HashSet<String>());
                GoLiteralIdentifier id = declaration.getMethodReceiver().getIdentifier();
                nameCheck(id, result);
                for (GoFunctionParameter parameter : declaration.getParameters()) {
                    for (GoLiteralIdentifier paramterId : parameter.getIdentifiers()) {
                        nameCheck(paramterId, result);
                    }
                }
                for (GoFunctionParameter parameter : declaration.getResults()) {
                    for (GoLiteralIdentifier paramterId : parameter.getIdentifiers()) {
                        nameCheck(paramterId, result);
                    }
                }

                visitElement(declaration);
                blockNameStack.pop();
                String name = declaration.getMethodReceiver().getType().getText() + "." + declaration.getName();
                if (name.startsWith("*")) {
                    name = name.substring(1);
                }
                if (methodNameSet.contains(name)) {
                    result.addProblem(declaration.getNameIdentifier(), GoBundle.message("error.redeclare"),
                            ProblemHighlightType.GENERIC_ERROR);
                    return;
                }
                methodNameSet.add(name);
            }

            @Override
            public void visitFunctionDeclaration(GoFunctionDeclaration declaration) {
                blockNameStack.push(new HashSet<String>());
                for (GoFunctionParameter parameter : declaration.getParameters()) {
                    for (GoLiteralIdentifier parameterIdentifier : parameter.getIdentifiers()) {
                        nameCheck(parameterIdentifier, result);
                    }
                }
                for (GoFunctionParameter parameter : declaration.getResults()) {
                    for (GoLiteralIdentifier parameterIdentifier : parameter.getIdentifiers()) {
                        nameCheck(parameterIdentifier, result);
                    }
                }

                visitElement(declaration);
                blockNameStack.pop();
                if (!declaration.isInit())
                    nameCheck(declaration.getNameIdentifier(), declaration.getName(), result);
            }

            @Override
            public void visitFunctionLiteral(GoLiteralFunction declaration) {
                blockNameStack.push(new HashSet<String>());
                for (GoFunctionParameter parameter : declaration.getParameters()) {
                    for (GoLiteralIdentifier parameterIdentifier : parameter.getIdentifiers()) {
                        nameCheck(parameterIdentifier, result);
                    }
                }
                for (GoFunctionParameter parameter : declaration.getResults()) {
                    for (GoLiteralIdentifier parameterIdentifier : parameter.getIdentifiers()) {
                        nameCheck(parameterIdentifier, result);
                    }
                }
                visitElement(declaration);
                blockNameStack.pop();

            }


            @Override
            public void visitTypeNameDeclaration(GoTypeNameDeclaration declaration) {
                nameCheck(declaration, declaration.getName(), result);
                visitElement(declaration);
            }

            @Override
            public void visitConstDeclaration(GoConstDeclaration declaration) {
                GoLiteralIdentifier[] ids = declaration.getIdentifiers();
                for (GoLiteralIdentifier id : ids) {
                    nameCheck(id, result);
                }
                visitElement(declaration);
            }

            @Override
            public void visitVarDeclaration(GoVarDeclaration declaration) {
                GoLiteralIdentifier[] ids = declaration.getIdentifiers();
                for (GoLiteralIdentifier id : ids) {
                    nameCheck(id, result);
                }
                visitElement(declaration);
            }

            @Override
            public void visitShortVarDeclaration(GoShortVarDeclaration declaration) {
                GoLiteralIdentifier[] ids = declaration.getIdentifiers();
                boolean isAllRepeat = true;
                for (GoLiteralIdentifier id : ids) {
                    if (id.isBlank()) {
                        continue;
                    }
                    String idName = id.getName();
                    if (!blockNameStack.peek().contains(idName)) {
                        isAllRepeat = false;
                        blockNameStack.peek().add(idName);
                    }
                }
                if (isAllRepeat) {
                    result.addProblem(ids[0], ids[ids.length - 1], GoBundle.message("error.no.new.variables.on.left.side"),
                            ProblemHighlightType.GENERIC_ERROR);
                }
                visitElement(declaration);
            }

            private void nameCheck(@Nullable GoLiteralIdentifier identifier, InspectionResult result) {
                if (identifier == null || identifier.isBlank())
                    return;

                nameCheck(identifier, identifier.getName(), result);
            }

            private void nameCheck(PsiElement errorElement, String name, InspectionResult result) {
                if (blockNameStack.peek().contains(name)) {
                    result.addProblem(errorElement, GoBundle.message("error.redeclare"),
                            ProblemHighlightType.GENERIC_ERROR);
                }
                blockNameStack.peek().add(name);
            }

        }.visitFile(file);
    }
}
TOP

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

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.