Skip to content

Commit

Permalink
Enable "add file to project" banner for query sync
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 587124227
  • Loading branch information
Googler authored and copybara-github committed Dec 4, 2023
1 parent 9b0ba6b commit 996776a
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,7 @@ static boolean sourceCoveredByProjectViewTargets(LocationContext context) {
}

private static Collection<TargetKey> fromTargetInfo(Collection<TargetInfo> targetInfos) {
return targetInfos
.stream()
return targetInfos.stream()
.map(t -> TargetKey.forPlainTarget(t.label))
.collect(toImmutableList());
}
Expand Down Expand Up @@ -334,10 +333,7 @@ private static WorkspacePath findBlazePackagePath(Project project, WorkspacePath
@Nullable
static LocationContext getContext(Project project, VirtualFile file) {
if (Blaze.getProjectType(project).equals(ProjectType.QUERY_SYNC)) {
// TODO(b/260643753) understand usages of this, and implement using BlazeProject instead
// Note the return type LocationContext includes BlazeProjectData to callers will need to
// change too.
return null;
throw new UnsupportedOperationException("AddSourceToProjectHelper#getContext");
}
BlazeProjectData syncData = BlazeProjectDataManager.getInstance(project).getBlazeProjectData();
if (syncData == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,14 @@
import com.google.idea.blaze.base.lang.buildfile.language.BuildFileType;
import com.google.idea.blaze.base.model.BlazeProjectData;
import com.google.idea.blaze.base.model.primitives.LanguageClass;
import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
import com.google.idea.blaze.base.projectview.ProjectViewSet;
import com.google.idea.blaze.base.qsync.QuerySyncManager;
import com.google.idea.blaze.base.qsync.QuerySyncProject;
import com.google.idea.blaze.base.scope.BlazeContext;
import com.google.idea.blaze.base.settings.Blaze;
import com.google.idea.blaze.base.settings.BlazeImportSettings;
import com.google.idea.blaze.base.settings.BlazeImportSettings.ProjectType;
import com.google.idea.blaze.base.settings.BlazeUserSettings;
import com.google.idea.blaze.base.settings.ui.BlazeUserSettingsCompositeConfigurable;
import com.google.idea.blaze.base.settings.ui.BlazeUserSettingsConfigurable;
Expand All @@ -49,11 +53,14 @@
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.EditorNotificationPanel;
import com.intellij.ui.EditorNotifications;
import com.intellij.ui.HyperlinkLabel;
import java.io.File;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
import javax.annotation.Nullable;

/**
Expand All @@ -69,7 +76,7 @@ public class ExternalFileProjectManagementHelper

private static final Key<EditorNotificationPanel> KEY = Key.create("add.source.to.project");

private final Set<File> suppressedFiles = new HashSet<>();
private final Set<VirtualFile> suppressedFiles = new HashSet<>();

private static final ImmutableList<String> IGNORED_FILE_TYPE_NAMES =
ImmutableList.of(
Expand Down Expand Up @@ -116,13 +123,33 @@ public EditorNotificationPanel createNotificationPanel(VirtualFile vf, FileEdito
return null;
}
if (!BlazeUserSettings.getInstance().getShowAddFileToProjectNotification()
|| suppressedFiles.contains(new File(vf.getPath()))) {
|| suppressedFiles.contains(vf)) {
return null;
}
File file = new File(vf.getPath());
if (!supportedFileType(file)) {
return null;
}
return createNotificationPanelByProjectType(vf);
}

@Nullable
private EditorNotificationPanel createNotificationPanelByProjectType(VirtualFile vf) {
ProjectType projectType = Blaze.getProjectType(project);
switch (projectType) {
case QUERY_SYNC:
return createNotificationPanelForQuerySync(vf);
case ASPECT_SYNC:
return createNotificationPanelForLegacySync(vf);
case UNKNOWN:
return null;
}
throw new AssertionError(projectType);
}

@Nullable
public EditorNotificationPanel createNotificationPanelForLegacySync(VirtualFile vf) {

LocationContext context = AddSourceToProjectHelper.getContext(project, vf);
if (context == null) {
return null;
Expand All @@ -142,22 +169,71 @@ public EditorNotificationPanel createNotificationPanel(VirtualFile vf, FileEdito
return null;
}

EditorNotificationPanel panel = new EditorNotificationPanel();
EditorNotificationPanel panel =
createPanel(
vf,
p ->
p.createActionLabel(
"Add file to project",
() -> {
AddSourceToProjectHelper.addSourceToProject(
project, context.workspacePath, inProjectDirectories, targetsFuture);
EditorNotifications.getInstance(project).updateNotifications(vf);
}));
panel.setVisible(false); // starts off not visible until we get the query results
panel.setText("Do you want to add this file to your project sources?");
panel.createActionLabel(
"Add file to project",

targetsFuture.addListener(
() -> {
AddSourceToProjectHelper.addSourceToProject(
project, context.workspacePath, inProjectDirectories, targetsFuture);
EditorNotifications.getInstance(project).updateNotifications(vf);
try {
List<TargetInfo> targets = targetsFuture.get();
if (!targets.isEmpty() || !inProjectDirectories) {
panel.setVisible(true);
}
} catch (InterruptedException | ExecutionException e) {
// ignore
}
},
MoreExecutors.directExecutor());
return panel;
}

@Nullable
private EditorNotificationPanel createNotificationPanelForQuerySync(VirtualFile virtualFile) {
QuerySyncProject querySyncProject =
QuerySyncManager.getInstance(project).getLoadedProject().orElse(null);
if (querySyncProject == null) {
return null;
}
if (!WorkspaceRoot.fromProject(project).isInWorkspace(virtualFile)) {
return null;
}

Path path = virtualFile.toNioPath();
// Project views do not support overriding a directory exclude, and the excluded directory may
// be imported from another file and so cannot be removed from the top-level file.
if (querySyncProject.containsPath(path) || querySyncProject.explicitlyExcludesPath(path)) {
return null;
}

return createPanel(
virtualFile,
p -> {
HyperlinkLabel unused =
p.createActionLabel("Add file to project", "Blaze.AddToQuerySyncProjectView");
});
}

private EditorNotificationPanel createPanel(
VirtualFile virtualFile, Consumer<EditorNotificationPanel> mainActionAdder) {
EditorNotificationPanel panel = new EditorNotificationPanel();
panel.setText("Do you want to add this file to your project sources?");
mainActionAdder.accept(panel);
panel.createActionLabel(
"Hide notification",
() -> {
// suppressed for this file until the editor is restarted
suppressedFiles.add(file);
EditorNotifications.getInstance(project).updateNotifications(vf);
suppressedFiles.add(virtualFile);
EditorNotifications.getInstance(project).updateNotifications(virtualFile);
});
panel.createActionLabel(
"Don't show again",
Expand All @@ -170,20 +246,6 @@ public EditorNotificationPanel createNotificationPanel(VirtualFile vf, FileEdito
BlazeUserSettingsCompositeConfigurable.ID,
BlazeUserSettingsConfigurable.SHOW_ADD_FILE_TO_PROJECT.label());
});

targetsFuture.addListener(
() -> {
try {
List<TargetInfo> targets = targetsFuture.get();
if (!targets.isEmpty() || !inProjectDirectories) {
panel.setVisible(true);
}
} catch (InterruptedException | ExecutionException e) {
// ignore
}
},
MoreExecutors.directExecutor());

return panel;
}

Expand Down
14 changes: 14 additions & 0 deletions base/src/com/google/idea/blaze/base/qsync/QuerySyncProject.java
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,20 @@ public boolean containsPath(Path absolutePath) {
return projectDefinition.isIncluded(workspaceRelative);
}

/**
* Returns true if {@code absolutePath} is specified in a project exclude.
*
* <p>A path not added or excluded the project definition will return false for both {@code
* containsPath} and {@code explicitlyExcludesPath}
*/
public boolean explicitlyExcludesPath(Path absolutePath) {
if (!workspaceRoot.isInWorkspace(absolutePath.toFile())) {
return false;
}
Path workspaceRelative = workspaceRoot.path().relativize(absolutePath);
return projectDefinition.isExcluded(workspaceRelative);
}

/** Returns all external dependencies of a given label */
public ImmutableSet<Label> externalDependenciesFor(Label label) {
return snapshotHolder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ public boolean isIncluded(Path workspacePath) {
return getIncludingContentRoot(workspacePath).isPresent();
}

public boolean isExcluded(Path workspacePath) {
return projectExcludes().stream().anyMatch(workspacePath::startsWith);
}

/**
* Returns the content root containing a workspace-relative path
*
Expand All @@ -163,7 +167,7 @@ public Optional<Path> getIncludingContentRoot(Path workspacePath) {
return contentRoot;
}

if (projectExcludes().stream().anyMatch(workspacePath::startsWith)) {
if (isExcluded(workspacePath)) {
// Path is excluded
return Optional.empty();
}
Expand Down

0 comments on commit 996776a

Please sign in to comment.