user-friendly navigation from stubs to the original groovy files

This commit is contained in:
peter
2010-07-12 11:56:32 +01:00
parent 613205a804
commit f27b09b3d5
3 changed files with 83 additions and 3 deletions
@@ -36,6 +36,11 @@ public class ExcludeFromStubGenerationAction extends AnAction implements DumbAwa
final PsiFile file = e.getData(DataKeys.PSI_FILE);
assert file != null && file.getLanguage() == GroovyFileType.GROOVY_LANGUAGE;
doExcludeFromStubGeneration(file);
}
public static void doExcludeFromStubGeneration(PsiFile file) {
final VirtualFile virtualFile = file.getVirtualFile();
assert virtualFile != null;
final Project project = file.getProject();
@@ -46,7 +51,6 @@ public class ExcludeFromStubGenerationAction extends AnAction implements DumbAwa
configurable.getExcludes().addEntry(new ExcludeEntryDescription(virtualFile, false, true, project));
}
});
}
public void update(AnActionEvent e) {
@@ -17,9 +17,16 @@ package org.jetbrains.plugins.groovy.compiler;
import com.intellij.openapi.compiler.CompilerManager;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.FileEditorManagerAdapter;
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
import com.intellij.ui.EditorNotificationPanel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.compiler.generator.GroovycStubGenerator;
@@ -47,6 +54,47 @@ public class GroovyCompilerLoader extends AbstractProjectComponent {
compilerManager.addTranslatingCompiler(new GroovyCompiler(myProject),
new HashSet<FileType>(Arrays.asList(GroovyFileType.GROOVY_FILE_TYPE, StdFileTypes.CLASS)),
new HashSet<FileType>(Arrays.asList(StdFileTypes.CLASS)));
myProject.getMessageBus().connect().subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerAdapter() {
@Override
public void fileOpened(FileEditorManager source, final VirtualFile file) {
if (file.getName().endsWith(".java") && file.getPath().contains(GroovycStubGenerator.GROOVY_STUBS)) {
final PsiClass psiClass = GroovycStubGenerator.findClassByStub(myProject, file);
if (psiClass != null) {
final FileEditorManager fileEditorManager = FileEditorManager.getInstance(myProject);
final FileEditor[] editors = fileEditorManager.getEditors(file);
if (editors.length != 0) {
decorateStubFile(file, fileEditorManager, editors[0]);
}
}
}
}
});
}
private void decorateStubFile(final VirtualFile file, FileEditorManager fileEditorManager, FileEditor editor) {
final EditorNotificationPanel panel = new EditorNotificationPanel();
panel.setText("This stub is generated for Groovy class to make Groovy-Java cross-compilation possible");
panel.createActionLabel("Go to the Groovy class", new Runnable() {
@Override
public void run() {
final PsiClass original = GroovycStubGenerator.findClassByStub(myProject, file);
if (original != null) {
original.navigate(true);
}
}
});
panel.createActionLabel("Exclude from stub generation", new Runnable() {
@Override
public void run() {
final PsiClass psiClass = GroovycStubGenerator.findClassByStub(myProject, file);
if (psiClass != null) {
ExcludeFromStubGenerationAction.doExcludeFromStubGeneration(psiClass.getContainingFile());
}
}
});
fileEditorManager.addTopComponent(editor, panel);
}
@NotNull
@@ -26,13 +26,19 @@ import com.intellij.openapi.compiler.ex.CompileContextEx;
import com.intellij.openapi.compiler.options.ExcludedEntriesConfiguration;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.Chunk;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.compiler.GroovyCompilerBase;
import org.jetbrains.plugins.groovy.compiler.GroovyCompilerConfiguration;
@@ -40,6 +46,7 @@ import org.jetbrains.plugins.groovy.compiler.GroovyCompilerConfiguration;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
@@ -47,6 +54,8 @@ import java.util.List;
*/
public class GroovycStubGenerator extends GroovyCompilerBase {
public static final String GROOVY_STUBS = "groovyStubs";
public GroovycStubGenerator(Project project) {
super(project);
}
@@ -93,8 +102,7 @@ public class GroovycStubGenerator extends GroovyCompilerBase {
@Override
protected void compileFiles(CompileContext compileContext, Module module,
final List<VirtualFile> toCompile, OutputSink sink, boolean tests) {
final String rootPath = CompilerPaths.getGeneratedDataDirectory(myProject) + "/groovyStubs/";
final File outDir = new File(rootPath + myProject.getLocationHash() + "/" + module.getName() + "/" + (tests ? "tests" : "production") + "/");
final File outDir = getStubOutput(module, tests);
outDir.mkdirs();
final VirtualFile tempOutput = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(outDir);
@@ -119,6 +127,26 @@ public class GroovycStubGenerator extends GroovyCompilerBase {
}
}
private static File getStubOutput(Module module, boolean tests) {
final Project project = module.getProject();
final String rootPath = CompilerPaths.getGeneratedDataDirectory(project).getPath() + "/" + GROOVY_STUBS + "/";
return new File(rootPath + project.getLocationHash() + "/" + module.getName() + "/" + (tests ? "tests" : "production") + "/");
}
@Nullable
public static PsiClass findClassByStub(Project project, VirtualFile stubFile) {
final String[] components = StringUtil.trimEnd(stubFile.getPath(), ".java").split("[\\\\/]");
final int stubs = Arrays.asList(components).indexOf(GROOVY_STUBS);
if (stubs < 0 || stubs >= components.length - 4) return null;
final String moduleName = components[stubs + 2];
final Module module = ModuleManager.getInstance(project).findModuleByName(moduleName);
if (module == null) return null;
final String fqn = StringUtil.join(Arrays.asList(components).subList(stubs + 4, components.length), ".");
return JavaPsiFacade.getInstance(project).findClass(fqn, GlobalSearchScope.moduleScope(module));
}
private void cleanDirectory(final VirtualFile dir) {
new WriteCommandAction(myProject) {
protected void run(Result result) throws Throwable {