Skip to content

Commit

Permalink
Replace some deprecated components with listeners/services (#524)
Browse files Browse the repository at this point in the history
This migrates some of the existing project components to a more modern (and recommended) service/listener architecture.
Also, some other minor deprecations were fixed along the way
  • Loading branch information
mzarnowski authored Apr 30, 2020
1 parent 0247248 commit 3d9dc39
Show file tree
Hide file tree
Showing 19 changed files with 234 additions and 281 deletions.
4 changes: 2 additions & 2 deletions common/com/twitter/intellij/pants/PantsBundle.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

package com.twitter.intellij.pants;

import com.intellij.CommonBundle;
import com.intellij.AbstractBundle;
import com.intellij.reference.SoftReference;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.PropertyKey;
Expand All @@ -18,7 +18,7 @@ public class PantsBundle {
private static final String BUNDLE = "com.twitter.intellij.pants.PantsBundle";

public static String message(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) {
return CommonBundle.message(getBundle(), key, params);
return AbstractBundle.message(getBundle(), key, params);
}

private static ResourceBundle getBundle() {
Expand Down
34 changes: 14 additions & 20 deletions common/com/twitter/intellij/pants/util/PantsUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import com.intellij.execution.process.ProcessOutput;
import com.intellij.ide.SaveAndSyncHandler;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
Expand All @@ -24,16 +24,11 @@
import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.externalSystem.ExternalSystemModulePropertyManager;
import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.ExternalSystemException;
import com.intellij.openapi.externalSystem.model.Key;
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode;
import com.intellij.openapi.externalSystem.service.internal.ExternalSystemExecuteTaskTask;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.module.Module;
Expand Down Expand Up @@ -86,6 +81,7 @@
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
Expand Down Expand Up @@ -308,7 +304,8 @@ public static Optional<VirtualFile> findBuildRoot(@NotNull Module module) {
Optional<VirtualFile> fromModuleFile = Optional.ofNullable(moduleFile).flatMap(PantsUtil::findBuildRoot);
if (fromModuleFile.isPresent()) {
return fromModuleFile;
} else {
}
else {
final ModuleRootManager rootManager = ModuleRootManager.getInstance(module);
for (VirtualFile contentRoot : rootManager.getContentRoots()) {
final Optional<VirtualFile> buildRoot = findBuildRoot(contentRoot);
Expand Down Expand Up @@ -538,7 +535,7 @@ public static boolean isPantsModule(@NotNull Module module) {
@NotNull
public static PantsSourceType getSourceTypeForTargetType(@Nullable String targetType, Boolean isSynthetic) {
try {
if(isSynthetic && targetType != null) {
if (isSynthetic && targetType != null) {
return PantsSourceType.SOURCE_GENERATED;
}
return targetType == null ? PantsSourceType.SOURCE :
Expand All @@ -554,7 +551,9 @@ public static boolean isResource(PantsSourceType sourceType) {
return sourceType == PantsSourceType.RESOURCE || sourceType == PantsSourceType.TEST_RESOURCE;
}

public static Optional<String> findModuleAddress(@NotNull Module module) {
public static Optional<String> findModuleAddress(@Nullable Module module) {
if (module == null) return Optional.empty();

ExternalSystemModulePropertyManager externalSystemModulePropertyManager = ExternalSystemModulePropertyManager.getInstance(module);
String path = externalSystemModulePropertyManager.getLinkedProjectPath();
if (path == null) {
Expand Down Expand Up @@ -615,7 +614,8 @@ public static Optional<String> getRelativeProjectPath(@NotNull File workDirector
public static void refreshAllProjects(@NotNull Project project) {
if (isPantsProject(project) || isSeedPantsProject(project)) {
ExternalProjectUtil.refresh(project, PantsConstants.SYSTEM_ID);
} else if (isBspProject(project)) {
}
else if (isBspProject(project)) {
ExternalProjectUtil.refresh(project, ProjectSystemId.findById("BSP"));
}
}
Expand Down Expand Up @@ -716,7 +716,7 @@ public static ProcessOutput getCmdOutput(

public static boolean isPythonAvailable() {
for (String pluginId : PYTHON_PLUGIN_IDS) {
final IdeaPluginDescriptor plugin = PluginManager.getPlugin(PluginId.getId(pluginId));
final IdeaPluginDescriptor plugin = PluginManagerCore.getPlugin(PluginId.getId(pluginId));
if (plugin != null && plugin.isEnabled()) {
return true;
}
Expand Down Expand Up @@ -903,10 +903,7 @@ public static Optional<VirtualFile> findPantsExecutable(@NotNull String projectP

public static Optional<File> findPantsExecutable(@NotNull File file) {
Optional<VirtualFile> vf = findPantsExecutable(LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file));
if (!vf.isPresent()) {
return Optional.empty();
}
return Optional.of(new File(vf.get().getPath()));
return vf.map(virtualFile -> new File(virtualFile.getPath()));
}

private static Optional<VirtualFile> findPantsExecutable(@Nullable VirtualFile file) {
Expand Down Expand Up @@ -961,11 +958,8 @@ public static void invalidatePluginCaches() {
SimpleExportResult.clearCache();
}

/**
* Copy from {@link ExternalSystemExecuteTaskTask#parseCmdParameters} because it is private.
*/
public static List<String> parseCmdParameters(Optional<String> cmdArgsLine) {
return cmdArgsLine.map(ParametersListUtil::parse).orElse(ContainerUtil.newArrayList());
public static List<String> parseCmdParameters(@Nullable String cmdArgsLine) {
return Optional.ofNullable(cmdArgsLine).map(ParametersListUtil::parse).orElse(new ArrayList<>());
}

public static void invokeLaterIfNeeded(Runnable task) {
Expand Down
10 changes: 4 additions & 6 deletions resources/META-INF/pants-python.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@
<!-- Licensed under the Apache License, Version 2.0 (see LICENSE). -->

<idea-plugin version="2">
<project-components>
<component>
<interface-class>com.twitter.intellij.pants.service.python.component.PantsPythonProjectComponent</interface-class>
<implementation-class>com.twitter.intellij.pants.service.python.component.impl.PantsPythonProjectComponentImpl</implementation-class>
</component>
</project-components>
<projectListeners>
<listener class="com.twitter.intellij.pants.service.python.component.PantsPythonRunConfigListener"
topic="com.intellij.execution.RunManagerListener"/>
</projectListeners>
<extensions defaultExtensionNs="com.intellij.plugins.pants">
<projectInfoModifier implementation="com.twitter.intellij.pants.service.python.PythonInfoModifier" order="before compressor"/>
<projectResolver implementation="com.twitter.intellij.pants.service.python.PythonPexResolver"/>
Expand Down
5 changes: 1 addition & 4 deletions resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@
<interface-class>com.twitter.intellij.pants.components.PantsProjectComponent</interface-class>
<implementation-class>com.twitter.intellij.pants.components.impl.PantsProjectComponentImpl</implementation-class>
</component>
<component>
<interface-class>com.twitter.intellij.pants.components.PantsProjectCache</interface-class>
<implementation-class>com.twitter.intellij.pants.components.impl.PantsProjectCacheImpl</implementation-class>
</component>
</project-components>

<actions>
Expand Down Expand Up @@ -167,6 +163,7 @@
conditionClass="com.twitter.intellij.pants.ui.PantsToolWindowFactoryCondition"/>
<externalSystemNotificationExtension implementation="com.twitter.intellij.pants.notification.PantsNotificationCustomizer"/>
<externalProjectDataService implementation="com.twitter.intellij.pants.service.project.metadata.PantsMetadataService"/>
<projectService serviceImplementation="com.twitter.intellij.pants.components.PantsProjectCache"/>
</extensions>
<projectListeners>
<listener class="com.twitter.intellij.pants.execution.SetJarManifestCommandLineShortener"
Expand Down
90 changes: 86 additions & 4 deletions src/com/twitter/intellij/pants/components/PantsProjectCache.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,94 @@
// Copyright 2015 Pants project contributors (see CONTRIBUTORS.md).
// Copyright 2020 Pants project contributors (see CONTRIBUTORS.md).
// Licensed under the Apache License, Version 2.0 (see LICENSE).

package com.twitter.intellij.pants.components;

import com.intellij.openapi.components.ProjectComponent;
import com.intellij.ProjectTopics;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootEvent;
import com.intellij.openapi.roots.ModuleRootListener;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.messages.MessageBusConnection;
import com.twitter.intellij.pants.util.PantsUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.model.java.JavaSourceRootType;

public interface PantsProjectCache extends ProjectComponent {
boolean folderContainsSourceRoot(@NotNull VirtualFile file);
import java.util.Comparator;
import java.util.TreeSet;

public class PantsProjectCache implements Disposable {
private static final Comparator<VirtualFile> VIRTUAL_FILE_COMPARATOR = (o1, o2) -> {
if (o1.isDirectory() && !o2.isDirectory()) {
return -1;
}
if (o2.isDirectory() && !o1.isDirectory()) {
return 1;
}

return StringUtil.naturalCompare(o1.getPath().toLowerCase(), o2.getPath().toLowerCase());
};


private final Project myProject;
private volatile TreeSet<VirtualFile> myProjectRoots = null;

public PantsProjectCache(Project project) {
myProject = project;
listenForRootsChange();
}

public static PantsProjectCache getInstance(@NotNull Project project) {
return ServiceManager.getService(project, PantsProjectCache.class);
}

public boolean folderContainsSourceRoot(@NotNull VirtualFile file) {
if (!file.isDirectory()) {
return false;
}
final TreeSet<VirtualFile> allRoots = getProjectRoots();
// find this file or the next one in natural order
final VirtualFile candidate = allRoots.ceiling(file);
return candidate != null && VfsUtil.isAncestor(file, candidate, false);
}

private synchronized TreeSet<VirtualFile> getProjectRoots() {
if (myProjectRoots == null) {
myProjectRoots = collectRoots();
}
return myProjectRoots;
}

@NotNull
private TreeSet<VirtualFile> collectRoots() {
final TreeSet<VirtualFile> result = new TreeSet<>(VIRTUAL_FILE_COMPARATOR);
final ProjectRootManager rootManager = ProjectRootManager.getInstance(myProject);
result.addAll(rootManager.getModuleSourceRoots(ContainerUtil.set(JavaSourceRootType.SOURCE, JavaSourceRootType.TEST_SOURCE)));
return result;
}

private void listenForRootsChange() {
if (myProject.isDefault() || !PantsUtil.isPantsProject(myProject)) {
return;
}
final MessageBusConnection connection = myProject.getMessageBus().connect(this);
connection.subscribe(
ProjectTopics.PROJECT_ROOTS, new ModuleRootListener() {
@Override
public void rootsChanged(@NotNull ModuleRootEvent event) {
myProjectRoots = null;
}
}
);
}

@Override
public void dispose() {
myProjectRoots = null;
}
}

This file was deleted.

Loading

0 comments on commit 3d9dc39

Please sign in to comment.