From f27b09b3d58b33e9d3e4feb01e104fbcfe07b4bd Mon Sep 17 00:00:00 2001 From: peter Date: Sun, 11 Jul 2010 20:36:21 +0100 Subject: [PATCH] user-friendly navigation from stubs to the original groovy files --- .../ExcludeFromStubGenerationAction.java | 6 ++- .../groovy/compiler/GroovyCompilerLoader.java | 48 +++++++++++++++++++ .../generator/GroovycStubGenerator.java | 32 ++++++++++++- 3 files changed, 83 insertions(+), 3 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/ExcludeFromStubGenerationAction.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/ExcludeFromStubGenerationAction.java index 1283d3152988..1933fabf3281 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/ExcludeFromStubGenerationAction.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/ExcludeFromStubGenerationAction.java @@ -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) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerLoader.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerLoader.java index 11f5e50feba6..a8ab5ded516e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerLoader.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerLoader.java @@ -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(Arrays.asList(GroovyFileType.GROOVY_FILE_TYPE, StdFileTypes.CLASS)), new HashSet(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 diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/generator/GroovycStubGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/generator/GroovycStubGenerator.java index 610e90131851..b0c87fa0078c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/generator/GroovycStubGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/generator/GroovycStubGenerator.java @@ -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 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 {