/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.plugin.ij.compiler;
import com.intellij.openapi.compiler.CompilerPaths;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileAdapter;
import com.intellij.openapi.vfs.VirtualFileEvent;
import com.intellij.openapi.vfs.VirtualFileListener;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.VirtualFileMoveEvent;
import gw.plugin.ij.compiler.parser.CompilerUtils;
import gw.plugin.ij.util.GosuModuleUtil;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
import java.util.Set;
public class GosuCompilerMonitor implements ProjectComponent {
private static final Logger LOG = Logger.getInstance(GosuCompilerMonitor.class);
private static final String GOSU_DEPENDENCIES_FILE_NAME = "gosu-dependencies.dat";
private VirtualFileListener vfsListener = new VirtualFileAdapter() {
private void updateDependents(VirtualFile file) {
final FileDependencyCache cache = getDependencyCache();
final Set<VirtualFile> dependents = cache.getDependentsOn(file);
for (VirtualFile dependent : dependents) {
final Module ijModule = GosuModuleUtil.getModule(GosuModuleUtil.findModuleForFile(dependent, project));
if (ijModule != null) {
final Pair<String, String> sourceFolderAndRelativePath = CompilerUtils.getSourceFolderAndRelativePath(ijModule, dependent);
final File outputFile = CompilerUtils.getOutputFile(ijModule, sourceFolderAndRelativePath);
final VirtualFile outputVirtualFile = LocalFileSystem.getInstance().findFileByIoFile(outputFile);
if (outputVirtualFile != null) {
try {
outputVirtualFile.delete(this);
} catch (IOException e) {
// Ignore
}
}
}
}
cache.remove(file);
}
@Override
public void fileMoved(@NotNull VirtualFileMoveEvent event) {
updateDependents(event.getFile());
}
@Override
public void fileDeleted(@NotNull VirtualFileEvent event) {
updateDependents(event.getFile());
}
};
private FileDependencyCache cache;
private final Project project;
private final VirtualFileManager vfsManager;
private final File cacheFile;
public static GosuCompilerMonitor getInstance(@NotNull Project project) {
return project.getComponent(GosuCompilerMonitor.class);
}
public GosuCompilerMonitor(@NotNull Project project, @NotNull VirtualFileManager vfsManager) {
this.project = project;
this.vfsManager = vfsManager;
this.cacheFile = new File(CompilerPaths.getCacheStoreDirectory(project), GOSU_DEPENDENCIES_FILE_NAME);
}
public synchronized FileDependencyCache getDependencyCache() {
if (cache == null) {
cache = new FileDependencyCache();
try {
cache.load(project, cacheFile);
setCacheInSync(true);
} catch (IOException e) {
cache.clear();
setCacheInSync(false);
}
}
return cache;
}
private boolean inSync = false;
public boolean isCacheInSync() {
return inSync;
}
public void setCacheInSync(boolean value) {
inSync = value;
}
// ProjectComponent
@Override
public void projectOpened() {
// Nothing to do
}
@Override
public void projectClosed() {
// Nothing to do
}
// BaseComponent
@Override
public void initComponent() {
this.vfsManager.addVirtualFileListener(vfsListener, project);
}
@Override
public void disposeComponent() {
vfsManager.removeVirtualFileListener(vfsListener);
if (cache != null) {
try {
cache.save(cacheFile);
} catch (IOException e) {
LOG.error("Error while saving cache file " + cacheFile, e);
}
}
}
// NamedComponent
@NotNull
@Override
public String getComponentName() {
return "GosuCompilerMonitor";
}
}