Java tutorial
// Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). // Licensed under the Apache License, Version 2.0 (see LICENSE). package com.twitter.intellij.pants.components.impl; import com.intellij.compiler.server.BuildManagerListener; import com.intellij.execution.RunManagerAdapter; import com.intellij.execution.RunManagerEx; import com.intellij.execution.RunnerAndConfigurationSettings; import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.AbstractProjectComponent; import com.intellij.openapi.externalSystem.ExternalSystemManager; import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.ExternalSystemUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.util.messages.MessageBusConnection; import com.twitter.intellij.pants.PantsBundle; import com.twitter.intellij.pants.components.PantsProjectComponent; import com.twitter.intellij.pants.execution.PantsMakeBeforeRun; import com.twitter.intellij.pants.service.project.PantsResolver; import com.twitter.intellij.pants.settings.PantsProjectSettings; import com.twitter.intellij.pants.settings.PantsSettings; import com.twitter.intellij.pants.util.PantsConstants; import com.twitter.intellij.pants.util.PantsUtil; import icons.PantsIcons; import org.jetbrains.annotations.NotNull; import java.util.Collections; import java.util.List; import java.util.UUID; public class PantsProjectComponentImpl extends AbstractProjectComponent implements PantsProjectComponent { protected PantsProjectComponentImpl(Project project) { super(project); } @Override public void projectOpened() { super.projectOpened(); if (myProject.isDefault()) { return; } StartupManager.getInstance(myProject).registerPostStartupActivity(new Runnable() { @Override public void run() { /** * Set project to allow dynamic classpath for JUnit run. Still requires any junit run to specify dynamic classpath in * {@link com.twitter.intellij.pants.execution.PantsClasspathRunConfigurationExtension#updateJavaParameters} * IDEA's logic: {@link com.intellij.execution.configurations.CommandLineBuilder} */ PropertiesComponent.getInstance(myProject).setValue("dynamic.classpath", true); if (PantsUtil.isSeedPantsProject(myProject)) { convertToPantsProject(); } registerExternalBuilderListener(); subscribeToRunConfigurationAddition(); final AbstractExternalSystemSettings pantsSettings = ExternalSystemApiUtil.getSettings(myProject, PantsConstants.SYSTEM_ID); final boolean resolverVersionMismatch = pantsSettings instanceof PantsSettings && ((PantsSettings) pantsSettings).getResolverVersion() != PantsResolver.VERSION; if (resolverVersionMismatch && PantsUtil.isPantsProject(myProject)) { final int answer = Messages.showYesNoDialog(myProject, PantsBundle.message("pants.project.generated.with.old.version", myProject.getName()), PantsBundle.message("pants.name"), PantsIcons.Icon); if (answer == Messages.YES) { PantsUtil.refreshAllProjects(myProject); } } } /** * To convert a seed Pants project to a full bloom pants project: * 1. Obtain the targets and project_path generated by `pants idea-plugin` from * workspace file `project.iws` via `PropertiesComponent` API. * 2. Generate a refresh spec based on the info above. * 3. Explicitly call {@link PantsUtil#refreshAllProjects}. */ private void convertToPantsProject() { String serializedTargets = PropertiesComponent.getInstance(myProject).getValue("targets"); String projectPath = PropertiesComponent.getInstance(myProject).getValue("project_path"); if (serializedTargets == null || projectPath == null) { return; } /** * Generate the import spec for the next refresh. */ final List<String> targetSpecs = PantsUtil.gson.fromJson(serializedTargets, PantsUtil.TYPE_LIST_STRING); final PantsProjectSettings pantsProjectSettings = new PantsProjectSettings(targetSpecs, projectPath, false, true); /** * Following procedures in {@link com.intellij.openapi.externalSystem.util.ExternalSystemUtil#refreshProjects}: * Make sure the setting is injected into the project for refresh. */ ExternalSystemManager<?, ?, ?, ?, ?> manager = ExternalSystemApiUtil .getManager(PantsConstants.SYSTEM_ID); if (manager == null) { return; } AbstractExternalSystemSettings settings = manager.getSettingsProvider().fun(myProject); settings.setLinkedProjectsSettings(Collections.singleton(pantsProjectSettings)); PantsUtil.refreshAllProjects(myProject); prepareGuiComponents(); } /** * Ensure GUI is set correctly because empty IntelliJ project (seed project in this case) * does not have these set by default. * 1. Make sure the project view is opened so view switch will follow. * 2. Pants tool window is initialized; otherwise no message can be shown when invoking `PantsCompile`. */ private void prepareGuiComponents() { if (!ApplicationManager.getApplication().isUnitTestMode()) { if (ToolWindowManager.getInstance(myProject).getToolWindow("Project") != null) { ToolWindowManager.getInstance(myProject).getToolWindow("Project").show(null); } ExternalSystemUtil.ensureToolWindowInitialized(myProject, PantsConstants.SYSTEM_ID); } } private void subscribeToRunConfigurationAddition() { RunManagerEx.getInstanceEx(myProject).addRunManagerListener(new RunManagerAdapter() { @Override public void runConfigurationAdded(@NotNull RunnerAndConfigurationSettings settings) { super.runConfigurationAdded(settings); if (!PantsUtil.isPantsProject(myProject) && !PantsUtil.isSeedPantsProject(myProject)) { return; } if (!PantsSettings.getInstance(myProject).isUsePantsMakeBeforeRun()) { return; } PantsMakeBeforeRun.replaceDefaultMakeWithPantsMake(myProject, settings); } }); } }); } /** * This registers the listener when IDEA external builder process calls Pants. */ private void registerExternalBuilderListener() { MessageBusConnection connection = myProject.getMessageBus().connect(); BuildManagerListener buildManagerListener = new BuildManagerListener() { @Override public void beforeBuildProcessStarted(Project project, UUID sessionId) { } @Override public void buildStarted(Project project, UUID sessionId, boolean isAutomake) { } @Override public void buildFinished(Project project, UUID sessionId, boolean isAutomake) { /** * Sync files as generated sources may have changed after external compile, * specifically when {@link com.twitter.intellij.pants.jps.incremental.PantsTargetBuilder} finishes, * except this code is run within IDEA core, thus having access to file sync calls. */ PantsUtil.synchronizeFiles(); } }; connection.subscribe(BuildManagerListener.TOPIC, buildManagerListener); } }