generate javadoc for scope (IDEA-20370)

This commit is contained in:
anna
2010-02-17 13:43:24 +03:00
parent f8926cef29
commit 4032f1aaa1
6 changed files with 85 additions and 388 deletions
@@ -1,177 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.javadoc;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.help.HelpManager;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.CommonBundle;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
final class GenerateJavadocDialog extends DialogWrapper {
private JRadioButton myForProjectRadio;
private JRadioButton myForPackageRadio;
private JCheckBox myIncludeSubpackagesCheckBox;
private final String myPackageName;
private final JavadocConfigurable myConfigurable;
private final Project myProject;
GenerateJavadocDialog(String packageName, Project project, JavadocConfiguration configuration) {
super(project, true);
myProject = project;
myConfigurable = configuration.createConfigurable();
setOKButtonText(JavadocBundle.message("javadoc.generate.start.button"));
myPackageName = "".equals(packageName) ? JavadocBundle.message("javadoc.generate.package.default") : packageName;
setTitle(JavadocBundle.message("javadoc.generate.title"));
init();
myConfigurable.reset();
}
protected JComponent createNorthPanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(4,8,8,0));
GridBagConstraints gbConstraints = new GridBagConstraints();
gbConstraints.gridy = 0;
gbConstraints.gridx = 0;
gbConstraints.gridwidth = 3;
gbConstraints.gridheight = 1;
gbConstraints.weightx = 1;
gbConstraints.fill = GridBagConstraints.BOTH;
gbConstraints.insets = new Insets(0,0,0,0);
myForProjectRadio = new JRadioButton(JavadocBundle.message("javadoc.generate.scope.whole.project"));
panel.add(myForProjectRadio, gbConstraints);
myForPackageRadio = new JRadioButton(
JavadocBundle.message("javadoc.generate.scope.package", (myPackageName != null ? " \"" + myPackageName + "\"" : "")));
gbConstraints.gridy++;
gbConstraints.insets = new Insets(0,0,0,0);
panel.add(myForPackageRadio, gbConstraints);
myIncludeSubpackagesCheckBox = new JCheckBox(JavadocBundle.message("javadoc.generate.scope.include.subpackages.checkbox"));
gbConstraints.gridy++;
gbConstraints.insets = new Insets(0,20,0,0);
panel.add(myIncludeSubpackagesCheckBox, gbConstraints);
ButtonGroup buttonGroup = new ButtonGroup();
buttonGroup.add(myForProjectRadio);
buttonGroup.add(myForPackageRadio);
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
myIncludeSubpackagesCheckBox.setEnabled(myForPackageRadio.isSelected());
}
};
myForProjectRadio.addActionListener(actionListener);
myForPackageRadio.addActionListener(actionListener);
return panel;
}
protected JComponent createCenterPanel() {
JPanel pane = new JPanel(new BorderLayout());
pane.setBorder(IdeBorderFactory.createTitledBorder(JavadocBundle.message("javadoc.generate.settings.group")));
pane.add(myConfigurable.createComponent(), BorderLayout.CENTER);
return pane;
}
void reset() {
myForPackageRadio.setEnabled(myPackageName != null);
myForPackageRadio.setSelected(myPackageName != null);
myForProjectRadio.setEnabled(true);
myForProjectRadio.setSelected(myPackageName == null);
myIncludeSubpackagesCheckBox.setSelected(myPackageName != null);
myIncludeSubpackagesCheckBox.setEnabled(myPackageName != null && myForPackageRadio.isSelected());
}
boolean isGenerationForProject() {
return myForProjectRadio.isSelected();
}
boolean isGenerationForPackage() {
return myForPackageRadio.isSelected();
}
boolean isGenerationWithSubpackages() {
return isGenerationForPackage() && myIncludeSubpackagesCheckBox.isSelected();
}
protected Action[] createActions(){
return new Action[]{getOKAction(), getCancelAction(), getHelpAction() };
}
protected void doOKAction() {
if (checkOutputDirectory(myConfigurable.getOutputDir())) {
myConfigurable.apply();
close(OK_EXIT_CODE);
}
}
protected void doHelpAction() {
HelpManager.getInstance().invokeHelp("editing.javadocGeneration");
}
private boolean checkOutputDirectory(String outputDirectory) {
if (outputDirectory == null || outputDirectory.trim().length() == 0) {
Messages.showMessageDialog(myProject, JavadocBundle.message("javadoc.generate.output.directory.not.specified"),
CommonBundle.getErrorTitle(), Messages.getErrorIcon());
return false;
}
File outputDir = new File(outputDirectory);
if (!outputDir.exists()){
int choice = Messages.showOkCancelDialog(
myProject,
JavadocBundle.message("javadoc.generate.output.directory.not.exists", outputDirectory),
JavadocBundle.message("javadoc.generate.message.title"),
Messages.getWarningIcon()
);
if (choice != 0) return false;
if (!outputDir.mkdirs()){
Messages.showMessageDialog(
myProject,
JavadocBundle.message("javadoc.generate.output.directory.creation.failed", outputDirectory),
CommonBundle.getErrorTitle(),
Messages.getErrorIcon()
);
return false;
}
}
else if (!outputDir.isDirectory()){
Messages.showMessageDialog(
myProject,
JavadocBundle.message("javadoc.generate.output.not.a.directory", outputDirectory),
CommonBundle.getErrorTitle(),
Messages.getErrorIcon()
);
return false;
}
return true;
}
}
@@ -21,7 +21,7 @@ import com.intellij.psi.PsiKeyword;
import javax.swing.*;
import java.io.File;
final class JavadocConfigurable implements Configurable {
public final class JavadocConfigurable implements Configurable {
private JavadocGenerationPanel myPanel;
private final JavadocConfiguration myConfiguration;
@@ -15,6 +15,7 @@
*/
package com.intellij.javadoc;
import com.intellij.analysis.AnalysisScope;
import com.intellij.execution.CantRunException;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
@@ -28,9 +29,6 @@ import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessTerminatedListener;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
@@ -38,7 +36,10 @@ import com.intellij.openapi.projectRoots.JavaSdk;
import com.intellij.openapi.projectRoots.JavaSdkType;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.ex.PathUtilEx;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.ProjectRootsTraversing;
import com.intellij.openapi.roots.SourceFolder;
import com.intellij.openapi.util.*;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
@@ -47,7 +48,6 @@ import com.intellij.util.containers.HashSet;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.io.File;
@@ -76,24 +76,10 @@ public class JavadocConfiguration implements ModuleRunProfile, JDOMExternalizabl
public boolean OPEN_IN_BROWSER = true;
private final Project myProject;
private GenerationOptions myGenerationOptions;
private AnalysisScope myGenerationScope;
public static final class GenerationOptions {
public final String myPackageFQName;
public final PsiDirectory myDirectory;
public final boolean isGenerationForPackage;
public final boolean isGenerationWithSubpackages;
public GenerationOptions(String packageFQName, PsiDirectory directory, boolean generationForPackage, boolean generationWithSubpackages) {
myPackageFQName = packageFQName;
myDirectory = directory;
isGenerationForPackage = generationForPackage;
isGenerationWithSubpackages = generationWithSubpackages;
}
}
public void setGenerationOptions(GenerationOptions generationOptions) {
myGenerationOptions = generationOptions;
public void setGenerationScope(AnalysisScope generationScope) {
myGenerationScope = generationScope;
}
public JavadocConfiguration(Project project) {
@@ -101,7 +87,7 @@ public class JavadocConfiguration implements ModuleRunProfile, JDOMExternalizabl
}
public RunProfileState getState(@NotNull final Executor executor, @NotNull final ExecutionEnvironment env) throws ExecutionException {
return new MyJavaCommandLineState(myProject, myGenerationOptions);
return new MyJavaCommandLineState(myProject, myGenerationScope);
}
public String getName() {
@@ -109,7 +95,7 @@ public class JavadocConfiguration implements ModuleRunProfile, JDOMExternalizabl
}
public void checkConfiguration() throws RuntimeConfigurationException {
if (myGenerationOptions == null) {
if (myGenerationScope == null) {
throw new RuntimeConfigurationError(JavadocBundle.message("javadoc.settings.not.specified"));
}
}
@@ -136,11 +122,11 @@ public class JavadocConfiguration implements ModuleRunProfile, JDOMExternalizabl
}
private class MyJavaCommandLineState extends CommandLineState {
private final GenerationOptions myGenerationOptions;
private final AnalysisScope myGenerationOptions;
private final Project myProject;
@NonNls private static final String INDEX_HTML = "index.html";
public MyJavaCommandLineState(Project project, GenerationOptions generationOptions) {
public MyJavaCommandLineState(Project project, AnalysisScope generationOptions) {
super(null);
myGenerationOptions = generationOptions;
myProject = project;
@@ -256,28 +242,7 @@ public class JavadocConfiguration implements ModuleRunProfile, JDOMExternalizabl
final Collection<String> packages = new HashSet<String>();
final Collection<String> sources = new HashSet<String>();
ApplicationManager.getApplication().runReadAction(
new Runnable(){
public void run() {
FileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
VirtualFile startingFile = null;
if (myGenerationOptions.isGenerationForPackage) {
if (!myGenerationOptions.isGenerationWithSubpackages) {
packages.add(myGenerationOptions.myPackageFQName);
return;
}
startingFile = myGenerationOptions.myDirectory.getVirtualFile();
}
MyContentIterator contentIterator = new MyContentIterator(myProject, packages, sources);
if (startingFile == null) {
fileIndex.iterateContent(contentIterator);
}
else {
fileIndex.iterateContentUnderDirectory(startingFile, contentIterator);
}
}
}
);
myGenerationOptions.accept(new MyContentIterator(myProject, packages, sources));
if (packages.size() + sources.size() == 0) {
throw new CantRunException(JavadocBundle.message("javadoc.generate.no.classes.in.selected.packages.error"));
}
@@ -302,7 +267,7 @@ public class JavadocConfiguration implements ModuleRunProfile, JDOMExternalizabl
}
}
private static class MyContentIterator implements ContentIterator {
private static class MyContentIterator extends PsiRecursiveElementWalkingVisitor {
private final PsiManager myPsiManager;
private final Collection<String> myPackages;
private final Collection<String> mySourceFiles;
@@ -313,72 +278,37 @@ public class JavadocConfiguration implements ModuleRunProfile, JDOMExternalizabl
mySourceFiles = sources;
}
public boolean processFile(VirtualFile fileOrDir) {
if (!fileOrDir.isInLocalFileSystem()) {
return true;
}
@Override
public void visitFile(PsiFile file) {
final VirtualFile fileOrDir = file.getVirtualFile();
if (fileOrDir == null) return;
if (!fileOrDir.isInLocalFileSystem()) return;
final Module module = ModuleUtil.findModuleForFile(fileOrDir, myPsiManager.getProject());
final PsiDirectory directory = getPsiDirectory(fileOrDir);
if (directory == null) {
if (!StdFileTypes.JAVA.equals(FileTypeManager.getInstance().getFileTypeByFile(fileOrDir))) {
return true;
}
PsiPackage psiPackage = getPsiPackage(fileOrDir.getParent());
if (psiPackage != null) {
if (psiPackage.getQualifiedName().length() == 0 || containsPackagePrefix(module, psiPackage.getQualifiedName())) {
mySourceFiles.add(PathUtil.getLocalPath(fileOrDir));
}
}
return true;
}
else {
processDirWithJavaFiles(directory, myPackages, mySourceFiles, module);
}
return true;
}
@Nullable
private PsiDirectory getPsiDirectory(VirtualFile fileOrDir) {
return fileOrDir != null ? myPsiManager.findDirectory(fileOrDir) : null;
}
@Nullable
private PsiPackage getPsiPackage(VirtualFile dir) {
PsiDirectory directory = getPsiDirectory(dir);
return directory != null ? JavaDirectoryService.getInstance().getPackage(directory) : null;
}
}
private static boolean processDirWithJavaFiles(PsiDirectory dir, Collection<String> packages, final Collection<String> sources, final Module module) {
PsiFile[] files = dir.getFiles();
for (PsiFile file : files) {
if (file instanceof PsiJavaFile) {
final PsiJavaFile javaFile = (PsiJavaFile)file;
if (containsPackagePrefix(module, javaFile.getPackageName())) {
sources.add(PathUtil.getLocalPath(javaFile.getVirtualFile()));
} else {
packages.add(javaFile.getPackageName());
mySourceFiles.add(PathUtil.getLocalPath(javaFile.getVirtualFile()));
}
else {
myPackages.add(javaFile.getPackageName());
}
return true;
}
}
return false;
}
public static boolean containsPackagePrefix(Module module, String packageFQName) {
if (module == null) return false;
final ContentEntry[] contentEntries = ModuleRootManager.getInstance(module).getContentEntries();
for (ContentEntry contentEntry : contentEntries) {
final SourceFolder[] sourceFolders = contentEntry.getSourceFolders();
for (SourceFolder sourceFolder : sourceFolders) {
final String packagePrefix = sourceFolder.getPackagePrefix();
final int prefixLength = packagePrefix.length();
if (prefixLength > 0 && packageFQName.startsWith(packagePrefix)) {
return true;
private static boolean containsPackagePrefix(Module module, String packageFQName) {
if (module == null) return false;
final ContentEntry[] contentEntries = ModuleRootManager.getInstance(module).getContentEntries();
for (ContentEntry contentEntry : contentEntries) {
final SourceFolder[] sourceFolders = contentEntry.getSourceFolders();
for (SourceFolder sourceFolder : sourceFolders) {
final String packagePrefix = sourceFolder.getPackagePrefix();
final int prefixLength = packagePrefix.length();
if (prefixLength > 0 && packageFQName.startsWith(packagePrefix)) {
return true;
}
}
}
return false;
}
return false;
}
}
@@ -16,34 +16,22 @@
package com.intellij.javadoc;
import com.intellij.CommonBundle;
import com.intellij.analysis.AnalysisScope;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.RunnerRegistry;
import com.intellij.execution.executors.DefaultRunExecutor;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ProgramRunner;
import com.intellij.execution.util.ExecutionErrorDialog;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.actionSystem.impl.SimpleDataContext;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.SourceFolder;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMExternalizable;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.psi.JavaDirectoryService;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiPackage;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
public final class JavadocGenerationManager extends AbstractProjectComponent implements JDOMExternalizable {
private final JavadocConfiguration myConfiguration;
@@ -56,59 +44,6 @@ public final class JavadocGenerationManager extends AbstractProjectComponent imp
myConfiguration = new JavadocConfiguration(project);
}
public void generateJavadoc(final PsiDirectory directory, DataContext dataContext) {
Component component = PlatformDataKeys.CONTEXT_COMPONENT.getData(dataContext);
final PsiPackage aPackage = directory != null ? JavaDirectoryService.getInstance().getPackage(directory) : null;
String packageFQName = aPackage != null ? aPackage.getQualifiedName() : null;
final GenerateJavadocDialog dialog = new GenerateJavadocDialog(packageFQName, myProject, myConfiguration);
dialog.reset();
dialog.show();
if (!dialog.isOK()) {
return;
}
if (component != null) {
dataContext = DataManager.getInstance().getDataContext(component);
}
else {
dataContext = SimpleDataContext.getProjectContext(myProject);
}
if (dialog.isGenerationForPackage() && !dialog.isGenerationWithSubpackages()) {
//remove package prefixes from javadoc.exe command
final Module module = directory != null ? ModuleUtil.findModuleForPsiElement(directory) : null;
if (module != null && packageFQName != null){
boolean reset = false;
final ContentEntry[] contentEntries = ModuleRootManager.getInstance(module).getContentEntries();
for (ContentEntry contentEntry : contentEntries) {
final SourceFolder[] sourceFolders = contentEntry.getSourceFolders();
for (SourceFolder sourceFolder : sourceFolders) {
final String packagePrefix = sourceFolder.getPackagePrefix();
final int prefixLength = packagePrefix.length();
if (prefixLength > 0 && packageFQName.startsWith(packagePrefix) && packageFQName.length() > prefixLength){
packageFQName = packageFQName.substring(prefixLength + 1);
reset = true;
break;
}
if (reset) break;
}
}
}
}
myConfiguration.setGenerationOptions(new JavadocConfiguration.GenerationOptions(packageFQName, directory, dialog.isGenerationForPackage(),
dialog.isGenerationWithSubpackages()));
try {
final ProgramRunner runner = RunnerRegistry.getInstance().getRunner(DefaultRunExecutor.EXECUTOR_ID, myConfiguration);
assert runner != null;
runner.execute(DefaultRunExecutor.getRunExecutorInstance(), new ExecutionEnvironment(myConfiguration, dataContext));
}
catch (ExecutionException e) {
ExecutionErrorDialog.show(e, CommonBundle.getErrorTitle(), myProject);
}
}
@NotNull
public String getComponentName() {
return "JavadocGenerationManager";
@@ -126,4 +61,15 @@ public final class JavadocGenerationManager extends AbstractProjectComponent imp
return myConfiguration;
}
public void generateJavadoc(AnalysisScope scope, DataContext dataContext) {
myConfiguration.setGenerationScope(scope);
try {
final ProgramRunner runner = RunnerRegistry.getInstance().getRunner(DefaultRunExecutor.EXECUTOR_ID, myConfiguration);
assert runner != null;
runner.execute(DefaultRunExecutor.getRunExecutorInstance(), new ExecutionEnvironment(myConfiguration, dataContext));
}
catch (ExecutionException e) {
ExecutionErrorDialog.show(e, CommonBundle.getErrorTitle(), myProject);
}
}
}
@@ -15,52 +15,50 @@
*/
package com.intellij.javadoc.actions;
import com.intellij.analysis.AnalysisScope;
import com.intellij.analysis.BaseAnalysisAction;
import com.intellij.analysis.BaseAnalysisActionDialog;
import com.intellij.ide.DataManager;
import com.intellij.javadoc.JavadocBundle;
import com.intellij.javadoc.JavadocConfigurable;
import com.intellij.javadoc.JavadocGenerationManager;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
public final class GenerateJavadocAction extends AnAction{
import javax.swing.*;
public void actionPerformed(AnActionEvent e) {
final DataContext dataContext = e.getDataContext();
final Project project = PlatformDataKeys.PROJECT.getData(dataContext);
final PsiDirectory dir = getDirectoryFromContext(dataContext);
JavadocGenerationManager.getInstance(project).generateJavadoc(dir, dataContext);
public final class GenerateJavadocAction extends BaseAnalysisAction{
private JavadocConfigurable myConfigurable;
public GenerateJavadocAction() {
super(JavadocBundle.message("javadoc.generate.title"), JavadocBundle.message("javadoc.generate.start.button"));
}
public void update(AnActionEvent event){
final Presentation presentation = event.getPresentation();
presentation.setEnabled(PlatformDataKeys.PROJECT.getData(event.getDataContext()) != null);
@Override
protected void analyze(@NotNull Project project, AnalysisScope scope) {
myConfigurable.apply();
JavadocGenerationManager.getInstance(project).generateJavadoc(scope, DataManager.getInstance().getDataContext());
dispose();
}
private static PsiDirectory getDirectoryFromContext(final DataContext dataContext) {
final Project project = PlatformDataKeys.PROJECT.getData(dataContext);
if (project == null) return null;
final Editor editor = PlatformDataKeys.EDITOR.getData(dataContext);
if (editor != null){
PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
if (psiFile != null) return psiFile.getContainingDirectory();
} else {
PsiElement element = LangDataKeys.PSI_ELEMENT.getData(dataContext);
if (element != null) {
if (element instanceof PsiDirectory) return (PsiDirectory)element;
else{
PsiFile psiFile = element.getContainingFile();
if (psiFile != null) return psiFile.getContainingDirectory();
}
} else {
//This is the case with GUI designer
VirtualFile virtualFile = PlatformDataKeys.VIRTUAL_FILE.getData(dataContext);
if (virtualFile != null && virtualFile.isValid()) {
PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile);
if (psiFile != null) return psiFile.getContainingDirectory();
}
}
@Override
protected JComponent getAdditionalActionSettings(Project project, BaseAnalysisActionDialog dialog) {
myConfigurable = JavadocGenerationManager.getInstance(project).getConfiguration().createConfigurable();
final JComponent component = myConfigurable.createComponent();
myConfigurable.reset();
return component;
}
@Override
protected void canceled() {
super.canceled();
dispose();
}
private void dispose() {
if (myConfigurable != null) {
myConfigurable.disposeUIResources();
myConfigurable = null;
}
return null;
}
}
@@ -25,7 +25,7 @@ javadoc.generate.arguments=&Other command line arguments:
javadoc.settings.title=Javadoc
javadoc.settings.not.specified=Generation options for javadoc not specified
javadoc.generate.no.jdk.path=JDK path is not specified\nCannot generate JavaDoc
javadoc.generate.no.classes.in.selected.packages.error=Selected package(s) contain no Java classes
javadoc.generate.no.classes.in.selected.packages.error=Selected scope contain no Java classes
javadoc.generate.exited=\njavadoc exited with exit code $EXIT_CODE$\n
javadoc.generate.output.directory.browse=Browse Output directory
javadoc.generate.locale=&Locale: