Package ro.redeul.google.go.inspection

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

package ro.redeul.google.go.inspection;

import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import ro.redeul.google.go.inspection.fix.*;
import ro.redeul.google.go.lang.psi.GoFile;
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.GoExpr;
import ro.redeul.google.go.lang.psi.expressions.literals.GoLiteralIdentifier;
import ro.redeul.google.go.lang.psi.expressions.literals.GoLiteralString;
import ro.redeul.google.go.lang.psi.expressions.primary.GoLiteralExpression;
import ro.redeul.google.go.lang.psi.expressions.primary.GoSelectorExpression;
import ro.redeul.google.go.lang.psi.statements.GoShortVarDeclaration;
import ro.redeul.google.go.lang.psi.toplevel.GoFunctionDeclaration;
import ro.redeul.google.go.lang.psi.toplevel.GoImportDeclaration;
import ro.redeul.google.go.lang.psi.toplevel.GoImportDeclarations;
import ro.redeul.google.go.lang.psi.types.GoPsiTypeName;
import ro.redeul.google.go.lang.psi.utils.GoPsiUtils;
import ro.redeul.google.go.lang.psi.visitors.GoRecursiveElementVisitor;
import ro.redeul.google.go.util.GoUtil;

import static ro.redeul.google.go.GoBundle.message;
import static ro.redeul.google.go.lang.psi.utils.GoPsiUtils.findParentOfType;
import static ro.redeul.google.go.lang.psi.utils.GoPsiUtils.resolveSafely;

public class UnresolvedSymbols extends AbstractWholeGoFileInspection {
    @Nls
    @NotNull
    @Override
    public String getDisplayName() {
        return "Highlights unresolved symbols";
    }

    @Override
    protected void doCheckFile(@NotNull GoFile file,
                               @NotNull final InspectionResult result) {
        new GoRecursiveElementVisitor() {
            @Override
            public void visitShortVarDeclaration(GoShortVarDeclaration declaration) {
                visitVarDeclaration(declaration);
            }

            @Override
            public void visitVarDeclaration(GoVarDeclaration declaration) {
                for (GoExpr expr : declaration.getExpressions()) {
                    visitElement(expr);
                }
            }

            @Override
            public void visitLiteralIdentifier(GoLiteralIdentifier identifier) {
                if (!identifier.isIota() && !identifier.isBlank() && !identifier.isNil()) {
                    tryToResolveReference(identifier, identifier.getName());
                }
            }

            @Override
            public void visitLiteralExpression(GoLiteralExpression expression) {
//                if (CallOrConversionReference.MATCHER.accepts(expression) ||
//                        BuiltinCallOrConversionReference.MATCHER.accepts(expression)) {
//                    tryToResolveReference(expression, expression.getText());
//                } else {
                    super.visitLiteralExpression(expression);
//                }
            }

            @Override
            public void visitTypeName(GoPsiTypeName typeName) {
                if (!typeName.isPrimitive()) {
                    tryToResolveReference(typeName, typeName.getName());
                }
            }

            private void tryToResolveReference(PsiElement element, String name) {
                if (GoPsiUtils.hasHardReferences(element) && resolveSafely(element, PsiElement.class) == null) {
                    LocalQuickFix[] fixes = null;
                    if (GoUtil.isFunctionNameIdentifier(element)) {
                        fixes = new LocalQuickFix[]{
                                new CreateFunctionFix(element),
                                new CreateClosureFunctionFix(element)
                        };
                    } else if (isLocalVariableIdentifier(element)) {
                        fixes = new LocalQuickFix[]{
                                new CreateLocalVariableFix(element),
                                new CreateGlobalVariableFix(element),
                                new CreateFunctionFix(element),
                                new CreateClosureFunctionFix(element),
                        };
                    } else if (isGlobalVariableIdentifier(element)) {
                        fixes = new LocalQuickFix[]{new CreateGlobalVariableFix(element)};
                    } else if (isUnqualifiedTypeName(element)) {
                        fixes = new LocalQuickFix[]{new CreateTypeFix(element)};
                    } else {
                        String text = element.getLastChild().getText();
                        if (text.length() != 0 && Character.isUpperCase(text.charAt(0))) {
                             /*
                             * We can also resolve nested packages
                             */
                            final GoFile containingFile = (GoFile) element.getContainingFile();
                            final GoImportDeclarations[] importDeclarations = containingFile.getImportDeclarations();

                            for (GoImportDeclarations goImportDeclarations : importDeclarations) {
                                final GoImportDeclaration[] declarations = goImportDeclarations.getDeclarations();
                                for (final GoImportDeclaration declaration : declarations) {

                                    final String visiblePackageName = declaration.getPackageAlias();
                                    if (visiblePackageName.equals(element.getFirstChild().getText())) {

                                        final Project project = element.getProject();


                                        PsiFile[] files = null;

                                        VirtualFile packageFile = null;
                                        GoLiteralString importPath = declaration.getImportPath();
                                        if (importPath != null)
                                            packageFile = project.getBaseDir().findFileByRelativePath("src/" + importPath.getValue());

                                        if (packageFile != null) {
                                            PsiDirectory directory = PsiManager.getInstance(project).findDirectory(packageFile);
                                            if (directory != null)
                                                files = directory.getFiles();

                                        }


                                        PsiFile workingFile = null;
                                        if (files != null && files.length != 0) {
                                            for (PsiFile psiFile : files) {
                                                if (psiFile.getName().equals(visiblePackageName) || psiFile.getName().equals(declaration.getPackageName())) {
                                                    workingFile = psiFile;
                                                    break;
                                                }
                                            }
                                            if (workingFile == null) {
                                                workingFile = files[0];
                                            }

                                            if (workingFile != null) {

                                                fixes = new LocalQuickFix[]{
                                                        new CreateFunctionFix(element, workingFile)
                                                };
                                            }
                                        }
                                    }

                                }
                            }
                        }
                    }
                    if (fixes == null)
                        fixes = LocalQuickFix.EMPTY_ARRAY;
                    result.addProblem(
                            element,
                            message("warning.unresolved.symbol", name),
                            ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, fixes);
                }
            }
        }.visitElement(file);
    }

    private static boolean isUnqualifiedTypeName(PsiElement element) {
        return element instanceof GoPsiTypeName ;
    }

    private static boolean isGlobalVariableIdentifier(PsiElement element) {
        return element instanceof GoLiteralIdentifier &&
                findParentOfType(element, GoSelectorExpression.class) == null &&
                findParentOfType(element, GoFunctionDeclaration.class) == null &&
                findParentOfType(element, GoVarDeclarations.class) != null;
    }

    private static boolean isLocalVariableIdentifier(PsiElement element) {
        return element instanceof GoLiteralIdentifier &&
                findParentOfType(element, GoSelectorExpression.class) == null &&
                findParentOfType(element, GoFunctionDeclaration.class) != null &&
                !element.textContains('.');
    }
}
TOP

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

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.