Package ro.redeul.google.go.runner

Source Code of ro.redeul.google.go.runner.GoTestConfigurationProducer

package ro.redeul.google.go.runner;

import com.intellij.execution.Location;
import com.intellij.execution.actions.ConfigurationContext;
import com.intellij.execution.actions.RunConfigurationProducer;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.patterns.ElementPattern;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import ro.redeul.google.go.GoFileType;
import ro.redeul.google.go.lang.psi.GoFile;
import ro.redeul.google.go.lang.psi.expressions.literals.GoLiteralIdentifier;
import ro.redeul.google.go.lang.psi.toplevel.GoFunctionDeclaration;
import ro.redeul.google.go.lang.psi.toplevel.GoFunctionParameter;
import ro.redeul.google.go.lang.psi.toplevel.GoFunctionParameterList;
import ro.redeul.google.go.lang.psi.toplevel.GoPackageDeclaration;
import ro.redeul.google.go.lang.psi.types.GoPsiTypePointer;
import ro.redeul.google.go.lang.psi.utils.GoFileUtils;

import java.io.File;

import static com.intellij.patterns.PlatformPatterns.psiElement;
import static com.intellij.patterns.StandardPatterns.string;

public class GoTestConfigurationProducer extends RunConfigurationProducer {

    private static final Logger LOG = Logger.getInstance(GoTestConfigurationProducer.class);

    public GoTestConfigurationProducer() {
        super(GoTestConfigurationType.getInstance());
    }

    protected GoTestConfigurationProducer(ConfigurationFactory configurationFactory) {
        super(configurationFactory);
    }

    @Override
    public boolean isConfigurationFromContext(RunConfiguration configuration, ConfigurationContext context) {
        if (configuration.getType() != getConfigurationType())
            return false;

        GoFile file = locationToFile(context.getLocation());
        if (file == null || !file.getName().endsWith("_test.go")) {
            return false;
        }

        PsiElement target = locationToTestFunction(context.getPsiLocation());
        GoTestConfiguration testConfig = (GoTestConfiguration) configuration;

        try {
            VirtualFile virtualFile = file.getVirtualFile();
            if (virtualFile == null)
                return false;

            Project project = file.getProject();
            Module module = ProjectRootManager.getInstance(project).getFileIndex().getModuleForFile(virtualFile);
            GoApplicationModuleBasedConfiguration configurationModule = testConfig.getConfigurationModule();
            String packageName = file.getPackageName();

            if (!StringUtil.equals(testConfig.packageDir, file.getContainingDirectory().getVirtualFile().getCanonicalPath()) ||
                    !StringUtil.equals(testConfig.workingDir, project.getBasePath()) ||
                    !(testConfig.testTargetType == GoTestConfiguration.TestTargetType.Package) ||
                    !(StringUtil.equals(packageName, file.getPackageName())) ||
                    !(configurationModule != null && module != null && module.equals(configurationModule.getModule())))
                return false;

            if (target instanceof GoFile) {
                GoTestConfiguration.Type executionMode =
                        fileDirContainsTestsOfSamePackage(project, (GoFile) target)
                                ? GoTestConfiguration.Type.Test
                                : GoTestConfiguration.Type.Benchmark;

                return testConfig.executeWhat == executionMode &&
                        StringUtil.isEmptyOrSpaces(testConfig.filter);
            } else if (target instanceof GoFunctionDeclaration) {

                GoFunctionDeclaration function = (GoFunctionDeclaration) target;

                if (!StringUtil.equals(testConfig.filter, "^" + function.getFunctionName() + "$"))
                    return false;

                if (FUNCTION_TEST.accepts(target))
                    return testConfig.executeWhat == GoTestConfiguration.Type.Test;

                if (FUNCTION_BENCHMARK.accepts(target))
                    return testConfig.executeWhat == GoTestConfiguration.Type.Benchmark;
            }

            return false;
        } catch (Exception ex) {
            LOG.error(ex);
        }

        return false;
    }

    @Override
    protected boolean setupConfigurationFromContext(RunConfiguration configuration, ConfigurationContext context, Ref sourceElement) {
        if (context.getPsiLocation() == null) {
            return false;
        }

        PsiFile file = context.getPsiLocation().getContainingFile();
        if (!(file instanceof GoFile)) {
            return false;
        }

        if (!file.getName().endsWith("_test.go")) {
            return false;
        }

        GoFile goFile = (GoFile) file;
        PsiElement psiSourceElement = (PsiElement) sourceElement.get();

        try {
            VirtualFile virtualFile = file.getVirtualFile();
            if (virtualFile == null) {
                return false;
            }

            psiSourceElement = locationToTestFunction(psiSourceElement);

            Project project = file.getProject();
            Module module = ProjectRootManager.getInstance(project).getFileIndex().getModuleForFile(virtualFile);
            GoTestConfiguration testConfig = (GoTestConfiguration) configuration;

            String packageName = goFile.getFullPackageName();
            testConfig.packageName = packageName;
            testConfig.packageDir = goFile.getContainingDirectory().getVirtualFile().getCanonicalPath();

            testConfig.testTargetType = GoTestConfiguration.TestTargetType.Package;

            if (psiSourceElement instanceof GoFile) {
                configuration.setName(packageName);
                // If there is any tests in current package, run in test mode.
                // Otherwise run in benchmark mode.
                if (fileDirContainsTestsOfSamePackage(project, (GoFile) psiSourceElement)) {
                    testConfig.executeWhat = GoTestConfiguration.Type.Test;
                } else {
                    testConfig.executeWhat = GoTestConfiguration.Type.Benchmark;
                }
            } else if (FUNCTION_TEST.accepts(psiSourceElement)) {
                String name = ((GoFunctionDeclaration) psiSourceElement).getName();
                configuration.setName(packageName + "." + name);

                testConfig.executeWhat = GoTestConfiguration.Type.Test;
                testConfig.filter = "^" + name + "$";
            } else if (FUNCTION_BENCHMARK.accepts(psiSourceElement)) {
                String name = ((GoFunctionDeclaration) psiSourceElement).getName();
                configuration.setName(packageName + "." + name);

                testConfig.executeWhat = GoTestConfiguration.Type.Benchmark;
                testConfig.filter = "^" + name + "$";
            }

            testConfig.workingDir = project.getBasePath();
            testConfig.setModule(module);

            return true;
        } catch (Exception ex) {
            LOG.error(ex);
        }

        return false;
    }

    private static final ElementPattern<GoFunctionDeclaration> FUNCTION_BENCHMARK =
            psiElement(GoFunctionDeclaration.class)
                    .withParent(psiElement(GoFile.class))
                    .withChild(
                            psiElement(GoFunctionParameterList.class)
                                    .withChild(
                                            psiElement(GoFunctionParameter.class)
                                                    .withChild(
                                                            psiElement(GoPsiTypePointer.class).withText("*testing.B")
                                                    )
                                    )
                                    .afterSibling(
                                            psiElement(GoLiteralIdentifier.class)
                                                    .withText(string().matches("Benchmark.*"))));

    private static final ElementPattern<GoFunctionDeclaration> FUNCTION_TEST =
            psiElement(GoFunctionDeclaration.class)
                    .withParent(psiElement(GoFile.class))
                    .withChild(
                            psiElement(GoFunctionParameterList.class)
                                    .withChild(
                                            psiElement(GoFunctionParameter.class)
                                                    .withChild(
                                                            psiElement(GoPsiTypePointer.class)
                                                                    .withText("*testing.T")
                                                    )
                                    )
                                    .afterSibling(
                                            psiElement(GoLiteralIdentifier.class)
                                                    .withText(string().matches("Test.*"))));

    private PsiElement locationToTestFunction(PsiElement location) {
        if (location == null)
            return null;

        while (location != null &&
                !FUNCTION_BENCHMARK.accepts(location) &&
                !FUNCTION_TEST.accepts(location) &&
                !(location instanceof GoFile)) {
            location = location.getParent();
        }

        return location;
    }

    private static boolean fileDirContainsTestsOfSamePackage(Project project, GoFile file) {
        VirtualFile virtualFile = file.getVirtualFile();
        if (virtualFile == null) {
            return false;
        }

        VirtualFile dir = virtualFile.getParent();
        if (dir == null || !dir.isDirectory()) {
            return false;
        }

        String packageName = getPackageName(file);
        if (packageName.isEmpty()) {
            return false;
        }

        for (VirtualFile child : dir.getChildren()) {
            if (child.getFileType() == GoFileType.INSTANCE &&
                    child.getNameWithoutExtension().endsWith("_test")) {
                GoFile childGoFile = (GoFile) PsiManager.getInstance(project).findFile(child);
                if (packageName.equals(getPackageName(childGoFile)) &&
                        fileContainsTest(childGoFile)) {
                    return true;
                }
            }
        }
        return false;
    }

    private static boolean fileContainsTest(GoFile file) {
        for (GoFunctionDeclaration func : GoFileUtils.getFunctionDeclarations(file)) {
            if (FUNCTION_TEST.accepts(func)) {
                return true;
            }
        }
        return false;
    }

    private static String getPackageName(GoFile file) {
        if (file == null) {
            return "";
        }

        GoPackageDeclaration pkg = file.getPackage();
        return pkg == null ? "" : pkg.getPackageName();
    }

    private static String getPackageNameForTesting(GoFile file) {
        String pkgName = file.getPackageImportPath();
        if (pkgName.endsWith("_test")) {
            String fileName = file.getName();
            String testedFileName = fileName.replace("_test", "");
            try {
                GoFile testedFile = (GoFile) file.getParent().findFile(testedFileName);

                return testedFile.getPackageImportPath();
            } catch (NullPointerException ignored) {

            }

        }
        return pkgName;
    }

    private String getGoFileDirRelativePath(GoFile goFile) {
        VirtualFile vf = goFile.getVirtualFile();
        if (vf == null) {
            return "";
        }

        vf = vf.getParent();
        String basePath = goFile.getProject().getBasePath();
        if (basePath == null || basePath.isEmpty()) {
            return "";
        }

        String filePath = vf.getPath();
        String relativePath = FileUtil.getRelativePath(basePath, filePath, File.separatorChar);
        if (relativePath == null) {
            return "";
        }

        return relativePath.replace(File.separatorChar, '/');
    }

    private GoFile locationToFile(Location location) {
        final PsiElement element = location.getPsiElement();
        final PsiFile file = element.getContainingFile();

        if (!(file instanceof GoFile)) {
            return null;
        }

        return (GoFile) file;
    }
}
TOP

Related Classes of ro.redeul.google.go.runner.GoTestConfigurationProducer

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.