package com.jetbrains.lang.dart.analyzer;
import com.intellij.ProjectTopics;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModuleRootEvent;
import com.intellij.openapi.roots.ModuleRootListener;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.util.PathUtil;
import com.intellij.util.SmartList;
import com.intellij.util.io.URLUtil;
import com.jetbrains.lang.dart.DartProjectComponent;
import com.jetbrains.lang.dart.sdk.DartSdk;
import com.jetbrains.lang.dart.sdk.DartSdkLibUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import static com.jetbrains.lang.dart.util.PubspecYamlUtil.PUBSPEC_YAML;
public class DartServerRootsHandler {
private final Project myProject;
private final List<String> myIncludedRoots = new SmartList<>();
private final List<String> myExcludedRoots = new SmartList<>();
public DartServerRootsHandler(Project project) {
myProject = project;
}
public void reset() {
myIncludedRoots.clear();
myExcludedRoots.clear();
}
public void ensureProjectServed() {
assert (myIncludedRoots.isEmpty());
assert (myExcludedRoots.isEmpty());
ProgressManager.getInstance().executeNonCancelableSection(() -> {
updateRoots();
final DartAnalysisServerService das = DartAnalysisServerService.getInstance(myProject);
das.updateCurrentFile();
das.updateVisibleFiles();
});
myProject.getMessageBus().connect().subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootListener() {
@Override
public void rootsChanged(final ModuleRootEvent event) {
updateRoots();
}
});
}
private void updateRoots() {
final DartSdk sdk = DartSdk.getDartSdk(myProject);
if (sdk == null || !DartAnalysisServerService.isDartSdkVersionSufficient(sdk)) {
DartAnalysisServerService.getInstance(myProject).stopServer();
}
final List<String> newIncludedRoots = new SmartList<>();
final List<String> newExcludedRoots = new SmartList<>();
if (sdk != null) {
@SuppressWarnings("ConstantConditions")
final String dotIdeaPath = PathUtil.getParentPath(myProject.getProjectFilePath());
if (dotIdeaPath.endsWith("/.idea")) {
newExcludedRoots.add(FileUtil.toSystemDependentName(dotIdeaPath));
}
for (Module module : DartSdkLibUtil.getModulesWithDartSdkEnabled(myProject)) {
final Set<String> excludedPackageSymlinkUrls = getExcludedPackageSymlinkUrls(module);
for (ContentEntry contentEntry : ModuleRootManager.getInstance(module).getContentEntries()) {
final String contentEntryUrl = contentEntry.getUrl();
if (contentEntryUrl.startsWith(URLUtil.FILE_PROTOCOL + URLUtil.SCHEME_SEPARATOR)) {
newIncludedRoots.add(FileUtil.toSystemDependentName(VfsUtilCore.urlToPath(contentEntryUrl)));
for (String excludedUrl : contentEntry.getExcludeFolderUrls()) {
if (excludedUrl.startsWith(contentEntryUrl) && !excludedPackageSymlinkUrls.contains(excludedUrl)) {
newExcludedRoots.add(FileUtil.toSystemDependentName(VfsUtilCore.urlToPath(excludedUrl)));
}
}
}
}
}
}
if (!myIncludedRoots.equals(newIncludedRoots) || !myExcludedRoots.equals(newExcludedRoots)) {
myIncludedRoots.clear();
myExcludedRoots.clear();
if (DartAnalysisServerService.getInstance(myProject).updateRoots(newIncludedRoots, newExcludedRoots)) {
myIncludedRoots.addAll(newIncludedRoots);
myExcludedRoots.addAll(newExcludedRoots);
}
}
}
private static Set<String> getExcludedPackageSymlinkUrls(@NotNull final Module module) {
final Set<String> result = new THashSet<>();
final Collection<VirtualFile> pubspecYamlFiles =
FilenameIndex.getVirtualFilesByName(module.getProject(), PUBSPEC_YAML, module.getModuleContentScope());
for (VirtualFile pubspecYamlFile : pubspecYamlFiles) {
result.addAll(DartProjectComponent.getExcludedPackageSymlinkUrls(module.getProject(), pubspecYamlFile));
}
return result;
}
}