diff --git a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java index 28677f16c619..47cc7b199968 100644 --- a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java +++ b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java @@ -16,13 +16,12 @@ package com.intellij.lang.java; -import com.intellij.codeInsight.CodeInsightBundle; -import com.intellij.codeInsight.documentation.DocumentationManager; import com.intellij.codeInsight.documentation.PlatformDocumentationUtil; import com.intellij.codeInsight.editorActions.CodeDocumentationUtil; import com.intellij.codeInsight.javadoc.JavaDocExternalFilter; import com.intellij.codeInsight.javadoc.JavaDocInfoGenerator; import com.intellij.codeInsight.javadoc.JavaDocUtil; +import com.intellij.codeInsight.javadoc.JavaDocumentationProviderBase; import com.intellij.lang.CodeDocumentationAwareCommenter; import com.intellij.lang.LangBundle; import com.intellij.lang.LanguageCommenters; @@ -36,7 +35,6 @@ import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.*; import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VirtualFile; @@ -44,7 +42,6 @@ import com.intellij.openapi.vfs.VirtualFileSystem; import com.intellij.psi.*; import com.intellij.psi.impl.beanProperties.BeanPropertyElement; import com.intellij.psi.impl.source.javadoc.PsiDocParamRef; -import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.javadoc.PsiDocTag; import com.intellij.psi.util.PsiFormatUtil; @@ -55,22 +52,19 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; import java.util.List; import java.util.Map; /** * @author Maxim.Mossienko */ -public class JavaDocumentationProvider implements CodeDocumentationProvider, ExternalDocumentationProvider { +public class JavaDocumentationProvider extends JavaDocumentationProviderBase implements CodeDocumentationProvider, ExternalDocumentationProvider { private static final Logger LOG = Logger.getInstance("#" + JavaDocumentationProvider.class.getName()); private static final String LINE_SEPARATOR = "\n"; @NonNls private static final String PARAM_TAG = "@param"; @NonNls private static final String RETURN_TAG = "@return"; @NonNls private static final String THROWS_TAG = "@throws"; - @NonNls public static final String HTML_EXTENSION = ".html"; - @NonNls public static final String PACKAGE_SUMMARY_FILE = "package-summary.html"; @Override public String getQuickNavigateInfo(PsiElement element, PsiElement originalElement) { @@ -258,6 +252,38 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext return buffer.toString(); } + @Override + @Nullable + public List findUrlForVirtualFile(final Project project, final VirtualFile virtualFile, final String relPath) { + final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); + Module module = fileIndex.getModuleForFile(virtualFile); + if (module == null) { + final VirtualFileSystem fs = virtualFile.getFileSystem(); + if (fs instanceof JarFileSystem) { + final VirtualFile jar = ((JarFileSystem)fs).getVirtualFileForJar(virtualFile); + if (jar != null) { + module = fileIndex.getModuleForFile(jar); + } + } + } + if (module != null) { + String[] javadocPaths = JavaModuleExternalPaths.getInstance(module).getJavadocUrls(); + final List httpRoots = PlatformDocumentationUtil.getHttpRoots(javadocPaths, relPath); + // if found nothing and the file is from library classes, fall back to order entries + if (httpRoots != null || !fileIndex.isInLibraryClasses(virtualFile)) { + return httpRoots; + } + } + + final List orderEntries = fileIndex.getOrderEntriesForFile(virtualFile); + for (OrderEntry orderEntry : orderEntries) { + final String[] files = JavadocOrderRootType.getUrls(orderEntry); + final List httpRoot = PlatformDocumentationUtil.getHttpRoots(files, relPath); + if (httpRoot != null) return httpRoot; + } + return null; + } + @SuppressWarnings({"HardCodedStringLiteral"}) public static String generateMethodInfo(PsiMethod method, PsiSubstitutor substitutor) { StringBuilder buffer = new StringBuilder(); @@ -382,6 +408,12 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext return buffer.toString(); } + @Override + @Nullable + public String generateExternalJavadoc(final PsiElement element) { + return JavaDocExternalFilter.filterInternalDocInfo(super.generateExternalJavadoc(element)); + } + @Override public PsiComment findExistingDocComment(final PsiComment comment) { if (comment instanceof PsiDocComment) { @@ -495,13 +527,7 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext @Override public String generateDoc(final PsiElement element, final PsiElement originalElement) { - if (element instanceof PsiMethodCallExpression) { - return getMethodCandidateInfo((PsiMethodCallExpression)element); - } - - - //external documentation finder - return generateExternalJavadoc(element); + return super.generateDoc(element, originalElement); } @Override @@ -509,14 +535,6 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext return null; } - @Nullable - public static String generateExternalJavadoc(final PsiElement element) { - final JavaDocInfoGenerator javaDocInfoGenerator = new JavaDocInfoGenerator(element.getProject(), element); - final List docURLs = getExternalJavaDocUrl(element); - return JavaDocExternalFilter.filterInternalDocInfo(javaDocInfoGenerator.generateDocInfo(docURLs)); - } - - @Nullable private static String fetchExternalJavadoc(final PsiElement element, String fromUrl, JavaDocExternalFilter filter) { try { @@ -531,183 +549,6 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext return null; } - private String getMethodCandidateInfo(PsiMethodCallExpression expr) { - final PsiResolveHelper rh = JavaPsiFacade.getInstance(expr.getProject()).getResolveHelper(); - final CandidateInfo[] candidates = rh.getReferencedMethodCandidates(expr, true); - final String text = expr.getText(); - if (candidates.length > 0) { - @NonNls final StringBuilder sb = new StringBuilder(); - - for (final CandidateInfo candidate : candidates) { - final PsiElement element = candidate.getElement(); - - if (!(element instanceof PsiMethod)) { - continue; - } - - final String str = PsiFormatUtil.formatMethod((PsiMethod)element, candidate.getSubstitutor(), - PsiFormatUtilBase.SHOW_NAME | - PsiFormatUtilBase.SHOW_TYPE | - PsiFormatUtilBase.SHOW_PARAMETERS, - PsiFormatUtilBase.SHOW_TYPE); - createElementLink(sb, element, StringUtil.escapeXml(str)); - } - - return CodeInsightBundle.message("javadoc.candiates", text, sb); - } - - return CodeInsightBundle.message("javadoc.candidates.not.found", text); - } - - private static void createElementLink(@NonNls final StringBuilder sb, final PsiElement element, final String str) { - sb.append("  "); - sb.append(str); - sb.append(""); - sb.append("
"); - } - - @Nullable - public static List getExternalJavaDocUrl(final PsiElement element) { - List urls = null; - - if (element instanceof PsiClass) { - urls = findUrlForClass((PsiClass)element); - } - else if (element instanceof PsiField) { - PsiField field = (PsiField)element; - PsiClass aClass = field.getContainingClass(); - if (aClass != null) { - urls = findUrlForClass(aClass); - if (urls != null) { - for (int i = 0; i < urls.size(); i++) { - urls.set(i, urls.get(i) + "#" + field.getName()); - } - } - } - } - else if (element instanceof PsiMethod) { - PsiMethod method = (PsiMethod)element; - PsiClass aClass = method.getContainingClass(); - if (aClass != null) { - final List classUrls = findUrlForClass(aClass); - - if (classUrls != null) { - urls = new ArrayList(); - String signature = formatMethodSignature(method); - for (String classUrl : classUrls) { - urls.add(classUrl + "#" + signature); - } - signature = PsiFormatUtil.formatMethod(method, PsiSubstitutor.EMPTY, - PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS, - PsiFormatUtilBase.SHOW_TYPE | PsiFormatUtilBase.SHOW_FQ_CLASS_NAMES, 999); - for (String classUrl : classUrls) { - urls.add(classUrl + "#" + signature); - } - } - } - } - else if (element instanceof PsiPackage) { - urls = findUrlForPackage((PsiPackage)element); - } - else if (element instanceof PsiDirectory) { - PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(((PsiDirectory)element)); - if (aPackage != null) { - urls = findUrlForPackage(aPackage); - } - } - - if (urls == null) { - return null; - } - else { - for (int i = 0; i < urls.size(); i++) { - urls.set(i, FileUtil.toSystemIndependentName(urls.get(i))); - } - return urls; - } - } - - public static String formatMethodSignature(PsiMethod method) { - return PsiFormatUtil.formatMethod(method, PsiSubstitutor.EMPTY, - PsiFormatUtilBase.SHOW_NAME | - PsiFormatUtilBase.SHOW_PARAMETERS | - PsiFormatUtilBase.SHOW_RAW_NON_TOP_TYPE, - PsiFormatUtilBase.SHOW_TYPE | - PsiFormatUtilBase.SHOW_FQ_CLASS_NAMES | - PsiFormatUtilBase.SHOW_RAW_NON_TOP_TYPE, - 999); - } - - @Nullable - public static List findUrlForClass(PsiClass aClass) { - String qName = aClass.getQualifiedName(); - if (qName == null) return null; - PsiFile file = aClass.getContainingFile(); - if (!(file instanceof PsiJavaFile)) return null; - String packageName = ((PsiJavaFile)file).getPackageName(); - - String relPath; - if (packageName.length() > 0) { - relPath = packageName.replace('.', '/') + '/' + qName.substring(packageName.length() + 1) + HTML_EXTENSION; - } - else { - relPath = qName + HTML_EXTENSION; - } - - final PsiFile containingFile = aClass.getContainingFile(); - if (containingFile == null) return null; - final VirtualFile virtualFile = containingFile.getVirtualFile(); - if (virtualFile == null) return null; - - return findUrlForVirtualFile(containingFile.getProject(), virtualFile, relPath); - } - - @Nullable - public static List findUrlForVirtualFile(final Project project, final VirtualFile virtualFile, final String relPath) { - final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); - Module module = fileIndex.getModuleForFile(virtualFile); - if (module == null) { - final VirtualFileSystem fs = virtualFile.getFileSystem(); - if (fs instanceof JarFileSystem) { - final VirtualFile jar = ((JarFileSystem)fs).getVirtualFileForJar(virtualFile); - if (jar != null) { - module = fileIndex.getModuleForFile(jar); - } - } - } - if (module != null) { - String[] javadocPaths = JavaModuleExternalPaths.getInstance(module).getJavadocUrls(); - final List httpRoots = PlatformDocumentationUtil.getHttpRoots(javadocPaths, relPath); - // if found nothing and the file is from library classes, fall back to order entries - if (httpRoots != null || !fileIndex.isInLibraryClasses(virtualFile)) { - return httpRoots; - } - } - - final List orderEntries = fileIndex.getOrderEntriesForFile(virtualFile); - for (OrderEntry orderEntry : orderEntries) { - final String[] files = JavadocOrderRootType.getUrls(orderEntry); - final List httpRoot = PlatformDocumentationUtil.getHttpRoots(files, relPath); - if (httpRoot != null) return httpRoot; - } - return null; - } - - @Nullable - public static List findUrlForPackage(PsiPackage aPackage) { - String qName = aPackage.getQualifiedName(); - qName = qName.replace('.', '/') + '/' + PACKAGE_SUMMARY_FILE; - for (PsiDirectory directory : aPackage.getDirectories()) { - List url = findUrlForVirtualFile(aPackage.getProject(), directory.getVirtualFile(), qName); - if (url != null) { - return url; - } - } - return null; - } - @Override public PsiElement getDocumentationElementForLink(final PsiManager psiManager, final String link, final PsiElement context) { return JavaDocUtil.findReferenceTarget(psiManager, link, context); diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java index 7f9592648447..12a9ce0b0ad0 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java @@ -18,7 +18,7 @@ package com.intellij.codeInsight.javadoc; import com.intellij.codeInsight.AnnotationUtil; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.codeInsight.ExternalAnnotationsManager; -import com.intellij.codeInsight.documentation.DocumentationManager; +import com.intellij.codeInsight.documentation.DocumentationManagerUtil; import com.intellij.lang.ASTNode; import com.intellij.lang.LangBundle; import com.intellij.openapi.diagnostic.Logger; @@ -1474,7 +1474,7 @@ public class JavaDocInfoGenerator { private void generateLink(StringBuilder buffer, PsiElement element, String label) { String refText = JavaDocUtil.getReferenceText(myProject, element); if (refText != null) { - DocumentationManager.createHyperlink(buffer, refText,label,false); + DocumentationManagerUtil.createHyperlink(buffer, refText,label,false); //return generateLink(buffer, refText, label, context, false); } } @@ -1501,7 +1501,7 @@ public class JavaDocInfoGenerator { } - DocumentationManager.createHyperlink(buffer, JavaDocUtil.getReferenceText(context.getProject(), target), label, plainLink); + DocumentationManagerUtil.createHyperlink(buffer, JavaDocUtil.getReferenceText(context.getProject(), target), label, plainLink); return label.length(); } diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocumentationProviderBase.java b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocumentationProviderBase.java index 47623748675e..64daa3dfa2c3 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocumentationProviderBase.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocumentationProviderBase.java @@ -1,8 +1,11 @@ package com.intellij.codeInsight.javadoc; import com.intellij.codeInsight.CodeInsightBundle; -import com.intellij.codeInsight.javadoc.JavaDocInfoGenerator; +import com.intellij.codeInsight.documentation.DocumentationManagerProtocol; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.util.PsiFormatUtil; @@ -10,24 +13,130 @@ import com.intellij.psi.util.PsiFormatUtilBase; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; import java.util.List; public class JavaDocumentationProviderBase { + @NonNls public static final String HTML_EXTENSION = ".html"; + @NonNls public static final String PACKAGE_SUMMARY_FILE = "package-summary.html"; + public String generateDoc(final PsiElement element, final PsiElement originalElement) { if (element instanceof PsiMethodCallExpression) { return getMethodCandidateInfo((PsiMethodCallExpression)element); } - //external documentation finder return generateExternalJavadoc(element); } @Nullable - public static String generateExternalJavadoc(final PsiElement element) { + public List getExternalJavaDocUrl(final PsiElement element) { + List urls = null; + + if (element instanceof PsiClass) { + urls = findUrlForClass((PsiClass)element); + } + else if (element instanceof PsiField) { + PsiField field = (PsiField)element; + PsiClass aClass = field.getContainingClass(); + if (aClass != null) { + urls = findUrlForClass(aClass); + if (urls != null) { + for (int i = 0; i < urls.size(); i++) { + urls.set(i, urls.get(i) + "#" + field.getName()); + } + } + } + } + else if (element instanceof PsiMethod) { + PsiMethod method = (PsiMethod)element; + PsiClass aClass = method.getContainingClass(); + if (aClass != null) { + final List classUrls = findUrlForClass(aClass); + + if (classUrls != null) { + urls = new ArrayList(); + String signature = formatMethodSignature(method); + for (String classUrl : classUrls) { + urls.add(classUrl + "#" + signature); + } + signature = PsiFormatUtil.formatMethod(method, PsiSubstitutor.EMPTY, + PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS, + PsiFormatUtilBase.SHOW_TYPE | PsiFormatUtilBase.SHOW_FQ_CLASS_NAMES, 999); + for (String classUrl : classUrls) { + urls.add(classUrl + "#" + signature); + } + } + } + } + else if (element instanceof PsiPackage) { + urls = findUrlForPackage((PsiPackage)element); + } + else if (element instanceof PsiDirectory) { + PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(((PsiDirectory)element)); + if (aPackage != null) { + urls = findUrlForPackage(aPackage); + } + } + + if (urls == null) { + return null; + } + else { + for (int i = 0; i < urls.size(); i++) { + urls.set(i, FileUtil.toSystemIndependentName(urls.get(i))); + } + return urls; + } + } + + @Nullable + public List findUrlForClass(PsiClass aClass) { + String qName = aClass.getQualifiedName(); + if (qName == null) return null; + PsiFile file = aClass.getContainingFile(); + if (!(file instanceof PsiJavaFile)) return null; + String packageName = ((PsiJavaFile)file).getPackageName(); + + String relPath; + if (packageName.length() > 0) { + relPath = packageName.replace('.', '/') + '/' + qName.substring(packageName.length() + 1) + HTML_EXTENSION; + } + else { + relPath = qName + HTML_EXTENSION; + } + + final PsiFile containingFile = aClass.getContainingFile(); + if (containingFile == null) return null; + final VirtualFile virtualFile = containingFile.getVirtualFile(); + if (virtualFile == null) return null; + + return findUrlForVirtualFile(containingFile.getProject(), virtualFile, relPath); + } + + @Nullable + public List findUrlForVirtualFile(final Project project, final VirtualFile virtualFile, final String relPath) { + return null; + } + + @Nullable + public List findUrlForPackage(PsiPackage aPackage) { + String qName = aPackage.getQualifiedName(); + qName = qName.replace('.', '/') + '/' + PACKAGE_SUMMARY_FILE; + for (PsiDirectory directory : aPackage.getDirectories()) { + List url = findUrlForVirtualFile(aPackage.getProject(), directory.getVirtualFile(), qName); + if (url != null) { + return url; + } + } + return null; + } + + @Nullable + public String generateExternalJavadoc(final PsiElement element) { final JavaDocInfoGenerator javaDocInfoGenerator = new JavaDocInfoGenerator(element.getProject(), element); final List docURLs = getExternalJavaDocUrl(element); - return JavaDocExternalFilter.filterInternalDocInfo(javaDocInfoGenerator.generateDocInfo(docURLs)); + return javaDocInfoGenerator.generateDocInfo(docURLs); } private String getMethodCandidateInfo(PsiMethodCallExpression expr) { @@ -58,11 +167,23 @@ public class JavaDocumentationProviderBase { } private static void createElementLink(@NonNls final StringBuilder sb, final PsiElement element, final String str) { - sb.append("  "); sb.append(str); sb.append(""); sb.append("
"); } + + public static String formatMethodSignature(PsiMethod method) { + return PsiFormatUtil.formatMethod(method, PsiSubstitutor.EMPTY, + PsiFormatUtilBase.SHOW_NAME | + PsiFormatUtilBase.SHOW_PARAMETERS | + PsiFormatUtilBase.SHOW_RAW_NON_TOP_TYPE, + PsiFormatUtilBase.SHOW_TYPE | + PsiFormatUtilBase.SHOW_FQ_CLASS_NAMES | + PsiFormatUtilBase.SHOW_RAW_NON_TOP_TYPE, + 999); + } + } diff --git a/platform/core-impl/src/com/intellij/codeInsight/documentation/DocumentationManagerProtocol.java b/platform/core-impl/src/com/intellij/codeInsight/documentation/DocumentationManagerProtocol.java index 3f51fa41f0bb..650f4be49ad2 100644 --- a/platform/core-impl/src/com/intellij/codeInsight/documentation/DocumentationManagerProtocol.java +++ b/platform/core-impl/src/com/intellij/codeInsight/documentation/DocumentationManagerProtocol.java @@ -1,4 +1,8 @@ package com.intellij.codeInsight.documentation; +import org.jetbrains.annotations.NonNls; + public interface DocumentationManagerProtocol { + @NonNls public static final String PSI_ELEMENT_PROTOCOL = "psi_element://"; + @NonNls public static final String DOC_ELEMENT_PROTOCOL = "doc_element://"; } diff --git a/platform/core-impl/src/com/intellij/codeInsight/documentation/DocumentationManagerUtil.java b/platform/core-impl/src/com/intellij/codeInsight/documentation/DocumentationManagerUtil.java index 98fd9bf33d02..dd47c42e1e96 100644 --- a/platform/core-impl/src/com/intellij/codeInsight/documentation/DocumentationManagerUtil.java +++ b/platform/core-impl/src/com/intellij/codeInsight/documentation/DocumentationManagerUtil.java @@ -1,4 +1,19 @@ package com.intellij.codeInsight.documentation; public class DocumentationManagerUtil { + @SuppressWarnings({"HardCodedStringLiteral"}) + public static void createHyperlink(StringBuilder buffer, String refText,String label,boolean plainLink) { + buffer.append(""); + if (!plainLink) { + buffer.append(""); + } + buffer.append(label); + if (!plainLink) { + buffer.append(""); + } + buffer.append(""); + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java index 5724c72986cb..80c092d816c2 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java @@ -74,7 +74,7 @@ import java.lang.ref.WeakReference; import java.util.*; import java.util.List; -public class DocumentationManager extends DockablePopupManager { +public class DocumentationManager extends DockablePopupManager implements DocumentationManagerProtocol { @NonNls public static final String JAVADOC_LOCATION_AND_SIZE = "javadoc.popup"; public static final DataKey SELECTED_QUICK_DOC_TEXT = DataKey.create("QUICK_DOC.SELECTED_TEXT"); @@ -89,8 +89,6 @@ public class DocumentationManager extends DockablePopupManager myDocInfoHintRef; private Component myPreviouslyFocused = null; public static final Key ORIGINAL_ELEMENT_KEY = Key.create("Original element"); - @NonNls public static final String PSI_ELEMENT_PROTOCOL = "psi_element://"; - @NonNls public static final String DOC_ELEMENT_PROTOCOL = "doc_element://"; private final ActionManagerEx myActionManagerEx; @@ -961,20 +959,8 @@ public class DocumentationManager extends DockablePopupManager"); - if (!plainLink) { - buffer.append(""); - } - buffer.append(label); - if (!plainLink) { - buffer.append(""); - } - buffer.append(""); + DocumentationManagerUtil.createHyperlink(buffer, refText, label, plainLink); } @Override