如何通过 Web link 导航或创建 class by JetBrains Toolbox

How to navigate or create a class through a web link by JetBrains Toolbox

我正在通过我的Chrome公司自动化测试扩展来集成 TestRail 和 IntelliJ IDEA。

现在我可以通过这种方式从测试用例 (TestRail) 导航到 class(IntelliJ IDEA):

jetbrains://idea/navigate/reference?project=automation&fqn=ru.company.qa.project.S125.C579

但是我无法创建 class 如果它不存在。

JetBrains Toolbox 可以通过 link 实现吗?

快速解决方案

添加class:

package ru.qa.summer.scene.plugin.navigation;

import com.intellij.ide.util.PsiNavigationSupport;
import com.intellij.openapi.application.JBProtocolCommand;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import ru.qa.summer.scene.plugin.util.SceneUtil;
import ru.qa.summer.support.data.FileAccessObject;
import ru.qa.summer.support.exceptions.AccessException;

import java.io.File;
import java.util.Map;

import static com.intellij.ide.impl.ProjectUtil.getOpenProjects;
import static com.intellij.openapi.vfs.VfsUtil.findFileByIoFile;
import static java.lang.Integer.parseInt;
import static java.lang.String.join;

public class JBProtocolNavigateOrCreateSceneCommand extends JBProtocolCommand {
    private static final String TARGET_NAME = "reference";
    private static final String PROJECT_NAME_KEY = "project";
    private static final String PATH_TO_SRC_NAME_KEY = "path-to-src";
    private static final String FILE_EXTENSION_NAME_KEY = "file-extension";
    private static final String FQN_NAME_KEY = "fqn";
    private static final String TOLERANCE_NAME_KEY = "tolerance";

    public JBProtocolNavigateOrCreateSceneCommand() {
        super("navigate-or-create-scene");
    }

    @Override
    public void perform(String target, @NotNull Map<String, String> parameters) {
        if (!target.equals(TARGET_NAME)) {
            return;
        }
        if (!parameters.containsKey(PROJECT_NAME_KEY) || !parameters.containsKey(PATH_TO_SRC_NAME_KEY)
                || !parameters.containsKey(FQN_NAME_KEY) || !parameters.containsKey(FILE_EXTENSION_NAME_KEY)) {
            return;
        }
        String projectName = parameters.get(PROJECT_NAME_KEY);
        for (Project project : getOpenProjects()) {
            if (project.getName().equals(projectName)) {
                performForProject(project, parameters);
                return;
            }
        }
    }

    private void performForProject(Project project, Map<String, String> parameters) {
        String path = parameters.get(PATH_TO_SRC_NAME_KEY);
        String fqn = parameters.get(FQN_NAME_KEY);
        String fileExtension = parameters.get(FILE_EXTENSION_NAME_KEY);
        int tolerance = parameters.containsKey(TOLERANCE_NAME_KEY) ? parseInt(parameters.get(TOLERANCE_NAME_KEY)) : 0;
        File ioFile = buildIoFile(project, path, fqn, fileExtension);
        if (ioFile.exists() && ioFile.isFile()) {
            navigate(project, findFileByIoFile(ioFile, true));
        } else {
            navigate(project, createFile(ioFile, fqn, tolerance));
        }
    }

    private File buildIoFile(Project project, String path, String fqn, String fileExtension) {
        String[] toClass = fqn.split("\.");
        toClass[toClass.length - 1] += "." + fileExtension;
        return new File(new File(project.getBasePath(), path).getAbsolutePath(), join("/", toClass));
    }

    private VirtualFile createFile(File ioFile, String fqn, int tolerance) {
        int i = tolerance + 1;
        File ioFileCursor = ioFile.getParentFile();
        do {
            if (ioFileCursor == null) {
                break;
            }
            if (ioFileCursor.exists() && ioFileCursor.isDirectory()) {
                try {
                    new FileAccessObject(ioFile).save(SceneUtil.createSceneClassTemplate(fqn));
                    return findFileByIoFile(ioFile, true);
                } catch (AccessException e) {
                    return null;
                }
            }
            ioFileCursor = ioFileCursor.getParentFile();
            i -= 1;
        } while (i > 0);
        return null;
    }

    private void navigate(Project project, VirtualFile file) {
        if (file != null && file.isValid()) {
            PsiNavigationSupport.getInstance().createNavigatable(project, file, 0).navigate(true);
        }
    }
}

为您的插件添加扩展:

<extensions defaultExtensionNs="com.intellij">
        <jbProtocolCommand implementation="ru.qa.summer.scene.plugin.navigation.JBProtocolNavigateOrCreateSceneCommand"/>
</extensions>

此解决方案允许导航或创建如下文件:

jetbrains://idea/navigate-or-create-scene/reference?project=automation&path-to-src=project/src/test/java&fqn=ru.company.qa.project.S269.C1289&file-extension=java&tolerance=1

查看 了解此功能的实施细节。

目前没有可以创建 class 文件的 JBProtocolCommand 实现。可以通过插件对其进行扩展。如果你想制作这样的插件,有什么问题,请post them here.