diff options
19 files changed, 770 insertions, 171 deletions
diff --git a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/CorextMessages.java b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/CorextMessages.java index d88431812f..338adbdfc2 100644 --- a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/CorextMessages.java +++ b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/CorextMessages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -26,9 +26,14 @@ public final class CorextMessages extends NLS { public static String Resources_fileModified; public static String JavaDocLocations_migrate_operation; + public static String JavaDocLocations_error_gettingJavadoc; public static String JavaDocLocations_error_readXML; public static String JavaDocLocations_migratejob_name; - + public static String JavaDocLocations_noAttachedJavadoc; + public static String JavaDocLocations_noAttachedSource; + public static String JavaDocLocations_noAttachments; + public static String JavaDocLocations_noInformation; + public static String History_error_serialize; public static String History_error_read; public static String TypeInfoHistory_consistency_check; diff --git a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/CorextMessages.properties b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/CorextMessages.properties index 084c3161c1..7801e94174 100644 --- a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/CorextMessages.properties +++ b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/CorextMessages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2000, 2009 IBM Corporation and others. +# Copyright (c) 2000, 2012 IBM Corporation and others. # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 # which accompanies this distribution, and is available at @@ -14,8 +14,13 @@ Resources_modifiedResources= There are modified resources Resources_fileModified= File ''{0}'' has been modified since the beginning of the operation JavaDocLocations_migrate_operation=Migrate Javadoc locations to build path attributes... +JavaDocLocations_error_gettingJavadoc=<em>Note: An exception occurred while getting the Javadoc. See log for details.</em> JavaDocLocations_error_readXML=Problems while reading the Javadoc locations from XML JavaDocLocations_migratejob_name=Migrate Javadoc locations to build path attributes +JavaDocLocations_noAttachedJavadoc=<em>Note: This element has no attached Javadoc and the Javadoc could not be found in the attached source.</em> +JavaDocLocations_noAttachedSource=<em>Note: This element has no attached source and the Javadoc could not be found in the attached Javadoc.</em> +JavaDocLocations_noAttachments=<em>Note: This element neither has attached source nor attached Javadoc and hence no Javadoc could be found.</em> +JavaDocLocations_noInformation=<em>Note: The Javadoc for this element could neither be found in the attached source nor the attached Javadoc.</em> JavaModelUtil_applyedit_operation=Applying changes History_error_serialize= Problems serializing information to XML ''{0}'' diff --git a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/codemanipulation/ImportReferencesCollector.java b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/codemanipulation/ImportReferencesCollector.java index fe5a65b2a0..63fe5651b0 100644 --- a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/codemanipulation/ImportReferencesCollector.java +++ b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/codemanipulation/ImportReferencesCollector.java @@ -86,7 +86,7 @@ public class ImportReferencesCollector extends GenericVisitor { private static boolean processJavadocComments(CompilationUnit astRoot) { // don't visit Javadoc for 'package-info' (bug 216432) if (astRoot != null && astRoot.getTypeRoot() != null) { - return !"package-info.java".equals(astRoot.getTypeRoot().getElementName()); //$NON-NLS-1$ + return !JavaModelUtil.PACKAGE_INFO_JAVA.equals(astRoot.getTypeRoot().getElementName()); } return true; } diff --git a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/javadoc/JavaDocLocations.java b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/javadoc/JavaDocLocations.java index 4c820c6fa1..3f813e7d0b 100644 --- a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/javadoc/JavaDocLocations.java +++ b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/javadoc/JavaDocLocations.java @@ -70,6 +70,7 @@ import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.core.IMethod; +import org.eclipse.jdt.core.IOpenable; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.IType; @@ -589,11 +590,20 @@ public class JavaDocLocations { buf.append(')'); } - public static String getBaseURL(IMember member) throws JavaModelException { - if (member.isBinary()) { + /** + * Returns the location of the Javadoc. + * + * @param element whose Javadoc location has to be found + * @param isBinary <code>true</code> if the Java element is from a binary container + * @return the location URL of the Javadoc or <code>null</code> if the location cannot be found + * @throws JavaModelException thrown when the Java element cannot be accessed + * @since 3.9 + */ + public static String getBaseURL(IJavaElement element, boolean isBinary) throws JavaModelException { + if (isBinary) { // Source attachment usually does not include Javadoc resources // => Always use the Javadoc location as base: - URL baseURL= JavaUI.getJavadocLocation(member, false); + URL baseURL= JavaUI.getJavadocLocation(element, false); if (baseURL != null) { if (baseURL.getProtocol().equals(JAR_PROTOCOL)) { // It's a JarURLConnection, which is not known to the browser widget. @@ -606,7 +616,7 @@ public class JavaDocLocations { return baseURL.toExternalForm(); } } else { - IResource resource= member.getResource(); + IResource resource= element.getResource(); if (resource != null) { /* * Too bad: Browser widget knows nothing about EFS and custom URL handlers, @@ -623,6 +633,43 @@ public class JavaDocLocations { } /** + * Returns the reason for why the Javadoc of the Java element could not be retrieved. + * + * @param element whose Javadoc could not be retrieved + * @param root the root of the Java element + * @return the String message for why the Javadoc could not be retrieved for the Java element or + * <code>null</code> if the Java element is from a source container + * @since 3.9 + */ + public static String getExplanationForMissingJavadoc(IJavaElement element, IPackageFragmentRoot root) { + String message= null; + try { + boolean isBinary= (root.getKind() == IPackageFragmentRoot.K_BINARY); + if (isBinary) { + boolean hasAttachedJavadoc= JavaDocLocations.getJavadocBaseLocation(element) != null; + boolean hasAttachedSource= root.getSourceAttachmentPath() != null; + IOpenable openable= element.getOpenable(); + boolean hasSource= openable.getBuffer() != null; + + // Provide hint why there's no Java doc + if (!hasAttachedSource && !hasAttachedJavadoc) + message= CorextMessages.JavaDocLocations_noAttachments; + else if (!hasAttachedJavadoc && !hasSource) + message= CorextMessages.JavaDocLocations_noAttachedJavadoc; + else if (!hasAttachedSource) + message= CorextMessages.JavaDocLocations_noAttachedSource; + else if (!hasSource) + message= CorextMessages.JavaDocLocations_noInformation; + + } + } catch (JavaModelException e) { + message= CorextMessages.JavaDocLocations_error_gettingJavadoc; + JavaPlugin.log(e); + } + return message; + } + + /** * Parse a URL from a String. This method first tries to treat <code>url</code> as a valid, encoded URL. * If that didn't work, it tries to recover from bad URLs, e.g. the unencoded form we used to use in persistent storage. * diff --git a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/util/JavaModelUtil.java b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/util/JavaModelUtil.java index 3a74b2660d..6399e3e71d 100644 --- a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/util/JavaModelUtil.java +++ b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/util/JavaModelUtil.java @@ -94,9 +94,22 @@ public final class JavaModelUtil { public static final String PACKAGE_INFO_JAVA= "package-info.java"; //$NON-NLS-1$ /** - * Finds a type container by container name. - * The returned element will be of type <code>IType</code> or a <code>IPackageFragment</code>. - * <code>null</code> is returned if the type container could not be found. + * The name of the package-info.class file. + * @since 3.9 + */ + public static final String PACKAGE_INFO_CLASS= "package-info.class"; //$NON-NLS-1$ + + /** + * The name of the package.html file. + * @since 3.9 + */ + public static final String PACKAGE_HTML= "package.html"; //$NON-NLS-1$ + + /** + * Finds a type container by container name. The returned element will be of type + * <code>IType</code> or a <code>IPackageFragment</code>. <code>null</code> is returned if the + * type container could not be found. + * * @param jproject The Java project defining the context to search * @param typeContainerName A dot separated name of the type container * @return returns the container diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/infoviews/InfoViewMessages.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/infoviews/InfoViewMessages.java index fa96bd2648..d77313eefb 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/infoviews/InfoViewMessages.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/infoviews/InfoViewMessages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -35,7 +35,7 @@ final class InfoViewMessages extends NLS { public static String GotoInputAction_label; public static String GotoInputAction_tooltip; public static String GotoInputAction_description; - + public static String OpenInBrowserAction_url_label; public static String OpenInBrowserAction_url_toolTip; @@ -53,10 +53,6 @@ final class InfoViewMessages extends NLS { public static String JavadocView_error_noBrowser_title; public static String JavadocView_error_noBrowser_message; public static String JavadocView_error_noBrowser_doNotWarn; - public static String JavadocView_noAttachments; - public static String JavadocView_noAttachedSource; - public static String JavadocView_noAttachedJavadoc; - public static String JavadocView_noInformation; public static String JavadocView_error_gettingJavadoc; public static String JavadocView_constantValue_hexValue; diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/infoviews/InfoViewMessages.properties b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/infoviews/InfoViewMessages.properties index 6d7b5c710f..11f492da4e 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/infoviews/InfoViewMessages.properties +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/infoviews/InfoViewMessages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2000, 2009 IBM Corporation and others. +# Copyright (c) 2000, 2012 IBM Corporation and others. # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 # which accompanies this distribution, and is available at @@ -39,10 +39,6 @@ JavadocView_action_toogleLinking_text=Link with Selection JavadocView_error_noBrowser_title= Javadoc view JavadocView_error_noBrowser_message= The HTML Browser widget could not be created. The standard text widget will be used instead. JavadocView_error_noBrowser_doNotWarn= Do not show this message again. -JavadocView_noAttachments= <em>Note: This element neither has attached source nor attached Javadoc and hence no Javadoc could be found.</em> -JavadocView_noAttachedSource= <em>Note: This element has no attached source and the Javadoc could not be found in the attached Javadoc.</em> -JavadocView_noAttachedJavadoc= <em>Note: This element has no attached Javadoc and the Javadoc could not be found in the attached source.</em> -JavadocView_noInformation= <em>Note: The Javadoc for this element could neither be found in the attached source nor the attached Javadoc.</em> JavadocView_error_gettingJavadoc= <em>Note: An exception occurred while getting the Javadoc. See log for details.</em> # The first parameter is the constant value string and the second is its hex representation JavadocView_constantValue_hexValue= {0} [{1}] diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/infoviews/JavadocView.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/infoviews/JavadocView.java index 08fbc8ef69..2f93cfaceb 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/infoviews/JavadocView.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/infoviews/JavadocView.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2012 IBM Corporation and others. + * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -41,12 +41,15 @@ import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Platform; +import org.eclipse.core.resources.IFile; + import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuManager; @@ -82,7 +85,9 @@ import org.eclipse.jface.text.TextSelection; import org.eclipse.jface.text.TextUtilities; import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.IWorkbenchCommandConstants; import org.eclipse.ui.IWorkbenchPage; @@ -95,6 +100,7 @@ import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.ActionFactory; import org.eclipse.ui.handlers.IHandlerService; +import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor; import org.eclipse.ui.texteditor.IAbstractTextEditorHelpContextIds; import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.ITextEditor; @@ -102,13 +108,16 @@ import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.jdt.core.IClassFile; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IField; +import org.eclipse.jdt.core.IJarEntryResource; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.ILocalVariable; import org.eclipse.jdt.core.IMember; -import org.eclipse.jdt.core.IOpenable; +import org.eclipse.jdt.core.IPackageDeclaration; +import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.ISourceRange; +import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.ITypeRoot; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; @@ -126,6 +135,7 @@ import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants; import org.eclipse.jdt.internal.corext.javadoc.JavaDocLocations; import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil; +import org.eclipse.jdt.internal.corext.util.JavaModelUtil; import org.eclipse.jdt.internal.corext.util.JdtFlags; import org.eclipse.jdt.internal.corext.util.Messages; @@ -328,7 +338,7 @@ public class JavadocView extends AbstractInfoView { * Action to open the selection in an external browser. If the selection is a java element its * corresponding javadoc is shown if possible. If it is an URL the URL's content is shown. * - * The action is disabled if the selection can not be opened. + * The action is disabled if the selection cannot be opened. * * @since 3.6 */ @@ -465,8 +475,7 @@ public class JavadocView extends AbstractInfoView { private LinkAction fToggleLinkAction; /** - * Action to open the attached Javadoc. - * + * Action to open the attached Javadoc. * @since 3.4 */ private OpenInBrowserAction fOpenBrowserAction; @@ -956,7 +965,12 @@ public class JavadocView extends AbstractInfoView { switch (input.getElementType()) { case IJavaElement.COMPILATION_UNIT: try { - javadocHtml= getJavadocHtml(((ICompilationUnit) input).getTypes(), part, selection, monitor); + IType[] types= ((ICompilationUnit) input).getTypes(); + if (types.length == 0 && JavaModelUtil.PACKAGE_INFO_JAVA.equals(input.getElementName())) { + javadocHtml= getJavadocHtml(new IJavaElement[] { input.getParent() }, part, selection, monitor); + } else { + javadocHtml= getJavadocHtml(types, part, selection, monitor); + } } catch (JavaModelException ex) { javadocHtml= null; } @@ -1053,8 +1067,8 @@ public class JavadocView extends AbstractInfoView { } /** - * Returns the Javadoc in HTML format. - * + * Returns the Javadoc of the Java element in HTML format. + * * @param result the Java elements for which to get the Javadoc * @param activePart the active part if any * @param selection the selection of the active site if any @@ -1070,20 +1084,52 @@ public class JavadocView extends AbstractInfoView { String base= null; if (nResults > 1) { - for (int i= 0; i < result.length; i++) { HTMLPrinter.startBulletList(buffer); IJavaElement curr= result[i]; - if (curr instanceof IMember || curr.getElementType() == IJavaElement.LOCAL_VARIABLE) + if (curr instanceof IMember || curr instanceof IPackageFragment || curr instanceof IPackageDeclaration || curr.getElementType() == IJavaElement.LOCAL_VARIABLE) { HTMLPrinter.addBullet(buffer, getInfoText(curr, null, false)); - HTMLPrinter.endBulletList(buffer); + HTMLPrinter.endBulletList(buffer); + } } - } else { - IJavaElement curr= result[0]; - if (curr instanceof IMember) { - final IMember member= (IMember)curr; + if (curr instanceof IPackageDeclaration || curr instanceof IPackageFragment) { + HTMLPrinter.addSmallHeader(buffer, getInfoText(curr, null, true)); + buffer.append("<br>"); //$NON-NLS-1$ + Reader reader= null; + String content= null; + try { + if (curr instanceof IPackageDeclaration) { + content= JavadocContentAccess2.getHTMLContent((IPackageDeclaration) curr); + } else if (curr instanceof IPackageFragment) { + content= JavadocContentAccess2.getHTMLContent((IPackageFragment) curr); + } + } catch (CoreException e) { + reader= new StringReader(InfoViewMessages.JavadocView_error_gettingJavadoc); + JavaPlugin.log(e); + } + IPackageFragmentRoot root= (IPackageFragmentRoot) curr.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); + try { + boolean isBinary= root.getKind() == IPackageFragmentRoot.K_BINARY; + if (content != null) { + base= JavaDocLocations.getBaseURL(curr, isBinary); + reader= new StringReader(content); + } else { + String explanationForMissingJavadoc= JavaDocLocations.getExplanationForMissingJavadoc(curr, root); + if (explanationForMissingJavadoc != null) { + reader= new StringReader(explanationForMissingJavadoc); + } + } + } catch (JavaModelException e) { + reader= new StringReader(InfoViewMessages.JavadocView_error_gettingJavadoc); + JavaPlugin.log(e); + } + if (reader != null) { + HTMLPrinter.addParagraph(buffer, reader); + } + } else if (curr instanceof IMember) { + final IMember member= (IMember) curr; String constantValue= null; if (member instanceof IField) { @@ -1095,9 +1141,9 @@ public class JavadocView extends AbstractInfoView { HTMLPrinter.addSmallHeader(buffer, getInfoText(member, constantValue, true)); try { - ISourceRange nameRange= ((IMember)curr).getNameRange(); + ISourceRange nameRange= ((IMember) curr).getNameRange(); if (SourceRange.isAvailable(nameRange)) { - ITypeRoot typeRoot= ((IMember)curr).getTypeRoot(); + ITypeRoot typeRoot= ((IMember) curr).getTypeRoot(); Region hoverRegion= new Region(nameRange.getOffset(), nameRange.getLength()); buffer.append("<br>"); //$NON-NLS-1$ JavadocHover.addAnnotations(buffer, curr, typeRoot, hoverRegion); @@ -1105,33 +1151,20 @@ public class JavadocView extends AbstractInfoView { } catch (JavaModelException e) { // no annotations this time... } - - Reader reader; + + Reader reader= null; try { String content= JavadocContentAccess2.getHTMLContent(member, true); - reader= content == null ? null : new StringReader(content); - - // Provide hint why there's no Javadoc - if (reader == null && member.isBinary()) { - boolean hasAttachedJavadoc= JavaDocLocations.getJavadocBaseLocation(member) != null; - IPackageFragmentRoot root= (IPackageFragmentRoot)member.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); - boolean hasAttachedSource= root != null && root.getSourceAttachmentPath() != null; - IOpenable openable= member.getOpenable(); - boolean hasSource= openable.getBuffer() != null; - - if (!hasAttachedSource && !hasAttachedJavadoc) - reader= new StringReader(InfoViewMessages.JavadocView_noAttachments); - else if (!hasAttachedJavadoc && !hasSource) - reader= new StringReader(InfoViewMessages.JavadocView_noAttachedJavadoc); - else if (!hasAttachedSource) - reader= new StringReader(InfoViewMessages.JavadocView_noAttachedSource); - else if (!hasSource) - reader= new StringReader(InfoViewMessages.JavadocView_noInformation); - + IPackageFragmentRoot root= (IPackageFragmentRoot) member.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); + if (content != null) { + base= JavaDocLocations.getBaseURL(member, member.isBinary()); + reader= new StringReader(content); } else { - base= JavaDocLocations.getBaseURL(member); + String explanationForMissingJavadoc= JavaDocLocations.getExplanationForMissingJavadoc(member, root); + if (explanationForMissingJavadoc != null) { + reader= new StringReader(explanationForMissingJavadoc); + } } - } catch (JavaModelException ex) { reader= new StringReader(InfoViewMessages.JavadocView_error_gettingJavadoc); JavaPlugin.log(ex.getStatus()); @@ -1151,7 +1184,7 @@ public class JavadocView extends AbstractInfoView { } } } - + if (buffer.length() == 0) return null; @@ -1166,14 +1199,14 @@ public class JavadocView extends AbstractInfoView { /** * Gets the label for the given member. - * + * * @param member the Java member * @param constantValue the constant value if any - * @param allowImage true if the java element image should be shown + * @param allowImage <code>true</code> if the Java element image should be shown * @return a string containing the member's label */ private String getInfoText(IJavaElement member, String constantValue, boolean allowImage) { - StringBuffer label= new StringBuffer(JavaElementLinks.getElementLabel(member, LABEL_FLAGS)); + StringBuffer label= new StringBuffer(JavaElementLinks.getElementLabel(member, getHeaderFlags(member))); if (member.getElementType() == IJavaElement.FIELD && constantValue != null) { label.append(constantValue); } @@ -1191,6 +1224,17 @@ public class JavadocView extends AbstractInfoView { return buf.toString(); } + + private long getHeaderFlags(IJavaElement element) { + switch (element.getElementType()) { + case IJavaElement.PACKAGE_FRAGMENT: + case IJavaElement.PACKAGE_DECLARATION: + return LABEL_FLAGS ^ JavaElementLabels.ALL_FULLY_QUALIFIED; + default: + return LABEL_FLAGS; + } + } + /* * @see org.eclipse.jdt.internal.ui.infoviews.AbstractInfoView#isIgnoringNewInput(org.eclipse.jdt.core.IJavaElement, org.eclipse.jface.viewers.ISelection) * @since 3.2 @@ -1232,35 +1276,60 @@ public class JavadocView extends AbstractInfoView { */ @Override protected IJavaElement findSelectedJavaElement(IWorkbenchPart part, ISelection selection) { - IJavaElement element; - try { - element= super.findSelectedJavaElement(part, selection); - - if (element == null && part instanceof JavaEditor && selection instanceof ITextSelection) { - - JavaEditor editor= (JavaEditor)part; - ITextSelection textSelection= (ITextSelection)selection; - - IDocumentProvider documentProvider= editor.getDocumentProvider(); - if (documentProvider == null) - return null; + IJavaElement element= super.findSelectedJavaElement(part, selection); + try { + //update the Javadoc view when package.html is selected in project explorer view + if (element == null && selection instanceof IStructuredSelection) { + Object selectedElement= ((IStructuredSelection) selection).getFirstElement(); + if (selectedElement instanceof IFile) { + IFile selectedFile= (IFile) selectedElement; + if (JavaModelUtil.PACKAGE_HTML.equals(selectedFile.getName())) { + element= JavaCore.create(selectedFile.getParent()); + } + } else if (selectedElement instanceof IJarEntryResource) { + IJarEntryResource jarEntryResource= (IJarEntryResource) selectedElement; + if (JavaModelUtil.PACKAGE_HTML.equals(jarEntryResource.getName())) { + Object parent= jarEntryResource.getParent(); + if (parent instanceof IJavaElement) { + element= (IJavaElement) parent; + } + } - IDocument document= documentProvider.getDocument(editor.getEditorInput()); - if (document == null) - return null; + } + } + + if (element == null && selection instanceof ITextSelection) { + ITextSelection textSelection= (ITextSelection) selection; + if (part instanceof AbstractDecoratedTextEditor) { + AbstractDecoratedTextEditor editor= (AbstractDecoratedTextEditor) part; + IDocumentProvider documentProvider= editor.getDocumentProvider(); + if (documentProvider != null) { + IEditorInput editorInput= editor.getEditorInput(); + IDocument document= documentProvider.getDocument(editorInput); + + if (document != null) { + ITypedRegion typedRegion= TextUtilities.getPartition(document, IJavaPartitions.JAVA_PARTITIONING, textSelection.getOffset(), false); + if (IJavaPartitions.JAVA_DOC.equals(typedRegion.getType())){ + element= TextSelectionConverter.getElementAtOffset((JavaEditor) part, textSelection); + } + else if (editorInput instanceof IFileEditorInput) { + IFile file= ((IFileEditorInput) editorInput).getFile(); + //update the Javadoc view when the content of the package.html is modified in the editor + if (JavaModelUtil.PACKAGE_HTML.equals(file.getName())) { + element= JavaCore.create(file.getParent()); + } + } + } + } + } + } - ITypedRegion typedRegion= TextUtilities.getPartition(document, IJavaPartitions.JAVA_PARTITIONING, textSelection.getOffset(), false); - if (IJavaPartitions.JAVA_DOC.equals(typedRegion.getType())) - return TextSelectionConverter.getElementAtOffset((JavaEditor)part, textSelection); - else - return null; - } else - return element; } catch (JavaModelException e) { return null; } catch (BadLocationException e) { return null; } + return element; } /* diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/AbstractJavaCompletionProposal.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/AbstractJavaCompletionProposal.java index 5ef393ff97..9c6aeb3d92 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/AbstractJavaCompletionProposal.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/AbstractJavaCompletionProposal.java @@ -563,7 +563,7 @@ public abstract class AbstractJavaCompletionProposal implements IJavaCompletionP try { element= getProposalInfo().getJavaElement(); if (element instanceof IMember) { - String base= JavaDocLocations.getBaseURL((IMember) element); + String base= JavaDocLocations.getBaseURL(element, ((IMember) element).isBinary()); if (base != null) { int endHeadIdx= buffer.indexOf("</head>"); //$NON-NLS-1$ buffer.insert(endHeadIdx, "\n<base href='" + base + "'>\n"); //$NON-NLS-1$ //$NON-NLS-2$ diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/LazyPackageCompletionProposal.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/LazyPackageCompletionProposal.java new file mode 100644 index 0000000000..f90e054a95 --- /dev/null +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/LazyPackageCompletionProposal.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2012 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.jdt.internal.ui.text.java; + +import org.eclipse.jdt.core.CompletionProposal; +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IJavaProject; + +import org.eclipse.jdt.ui.text.java.JavaContentAssistInvocationContext; + +public class LazyPackageCompletionProposal extends LazyJavaCompletionProposal { + + private final ICompilationUnit fCompilationUnit; + + public LazyPackageCompletionProposal(CompletionProposal proposal, JavaContentAssistInvocationContext context) { + super(proposal, context); + fCompilationUnit= context.getCompilationUnit(); + } + + @Override + protected ProposalInfo computeProposalInfo() { + + IJavaProject project; + if (fCompilationUnit != null) + project= fCompilationUnit.getJavaProject(); + else + project= fInvocationContext.getProject(); + if (project != null) { + return new PackageProposalInfo(project, fProposal); + } + + return super.computeProposalInfo(); + } + +} diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/PackageProposalInfo.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/PackageProposalInfo.java new file mode 100644 index 0000000000..5d4a503090 --- /dev/null +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/PackageProposalInfo.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2012 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.jdt.internal.ui.text.java; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; + +import org.eclipse.jdt.core.CompletionProposal; +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaModelException; + +public class PackageProposalInfo extends ProposalInfo { + + private boolean fJavaElementResolved= false; + + private final IJavaProject fJavaProject; + + private final CompletionProposal fProposal; + + PackageProposalInfo(IJavaProject project, CompletionProposal proposal) { + Assert.isNotNull(project); + Assert.isNotNull(proposal); + fJavaProject= project; + fProposal= proposal; + } + + @Override + public IJavaElement getJavaElement() throws JavaModelException { + if (!fJavaElementResolved) { + fJavaElementResolved= true; + fElement= resolvePackage(); + } + return fElement; + } + + /** + * Resolves to a PackageFragment. + * + * @return the <code>IPackageFragment</code> or <code>null</code> if no Java element can be found + * @throws JavaModelException thrown if the given path is <code>null</code> or absolute + * @since 3.9 + */ + private IJavaElement resolvePackage() throws JavaModelException { + char[] signature= fProposal.getDeclarationSignature(); + if (signature != null) { + String typeName= String.valueOf(signature); + typeName= typeName.replace('.', IPath.SEPARATOR); + return fJavaProject.findElement(new Path(typeName)); + } + return null; + } +} diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/ProposalInfo.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/ProposalInfo.java index 9eb4ac52bb..3fb7461289 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/ProposalInfo.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/ProposalInfo.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,10 +10,15 @@ *******************************************************************************/ package org.eclipse.jdt.internal.ui.text.java; +import java.io.IOException; + +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IMember; +import org.eclipse.jdt.core.IPackageDeclaration; +import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.internal.ui.JavaPlugin; @@ -70,29 +75,30 @@ public class ProposalInfo { private String computeInfo(IProgressMonitor monitor) { try { final IJavaElement javaElement= getJavaElement(); - if (javaElement instanceof IMember) { - IMember member= (IMember) javaElement; - return extractJavadoc(member, monitor); - } - } catch (JavaModelException e) { + return extractJavadoc(javaElement); + } catch (Exception e) { JavaPlugin.log(e); } return null; } /** - * Extracts the javadoc for the given <code>IMember</code> and returns it - * as HTML. - * - * @param member the member to get the documentation for - * @param monitor a progress monitor - * @return the javadoc for <code>member</code> or <code>null</code> if - * it is not available - * @throws JavaModelException if accessing the javadoc fails + * Extracts the Javadoc for the given Java element and returns it as HTML. + * + * @param element the Java element to get the documentation for + * @return the Javadoc for Java element or <code>null</code> if the Javadoc is not available + * @throws CoreException if the file containing the package Javadoc could not be successfully + * connected + * @throws IOException if an I/O error occurs while accessing the file containing the package + * Javadoc */ - private String extractJavadoc(IMember member, IProgressMonitor monitor) throws JavaModelException { - if (member != null) { - return JavadocContentAccess2.getHTMLContent(member, true); + private String extractJavadoc(IJavaElement element) throws IOException, CoreException { + if (element instanceof IMember) { + return JavadocContentAccess2.getHTMLContent((IMember) element, true); + } else if (element instanceof IPackageDeclaration) { + return JavadocContentAccess2.getHTMLContent((IPackageDeclaration) element); + } else if (element instanceof IPackageFragment) { + return JavadocContentAccess2.getHTMLContent((IPackageFragment) element); } return null; } diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/JavaHoverMessages.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/JavaHoverMessages.java index 49cf608178..c118849469 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/JavaHoverMessages.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/JavaHoverMessages.java @@ -31,10 +31,6 @@ final class JavaHoverMessages extends NLS { public static String JavadocHover_back; public static String JavadocHover_back_toElement_toolTip; - public static String JavadocHover_noAttachments; - public static String JavadocHover_noAttachedJavadoc; - public static String JavadocHover_noAttachedSource; - public static String JavadocHover_noInformation; public static String JavadocHover_constantValue_hexValue; public static String JavadocHover_error_gettingJavadoc; public static String JavadocHover_forward; diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/JavaHoverMessages.properties b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/JavaHoverMessages.properties index e73ed43bba..606c21fdc3 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/JavaHoverMessages.properties +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/JavaHoverMessages.properties @@ -23,10 +23,6 @@ NLSStringHover_NLSStringHover_PropertiesFileCouldNotBeReadWarning=<b>Warning:</b NLSStringHover_open_in_properties_file=Open in Properties File JavadocHover_back= Back JavadocHover_back_toElement_toolTip=Back to {0} -JavadocHover_noAttachments= <em>Note: This element neither has attached source nor attached Javadoc and hence no Javadoc could be found.</em> -JavadocHover_noAttachedSource= <em>Note: This element has no attached source and the Javadoc could not be found in the attached Javadoc.</em> -JavadocHover_noAttachedJavadoc= <em>Note: This element has no attached Javadoc and the Javadoc could not be found in the attached source.</em> -JavadocHover_noInformation= <em>Note: The Javadoc for this element could neither be found in the attached source nor the attached Javadoc.</em> # The first parameter is the constant value string and the second is its hex representation JavadocHover_constantValue_hexValue={0} [{1}] JavadocHover_error_gettingJavadoc= <em>Note: An exception occurred while getting the Javadoc. See log for details.</em> diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/JavadocHover.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/JavadocHover.java index dd436f8d9a..339d5da992 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/JavadocHover.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/JavadocHover.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2012 IBM Corporation and others. + * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -26,6 +26,7 @@ import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Platform; @@ -61,7 +62,7 @@ import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMember; -import org.eclipse.jdt.core.IOpenable; +import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.ITypeRoot; import org.eclipse.jdt.core.JavaCore; @@ -268,7 +269,7 @@ public class JavadocHover extends AbstractJavaEditorTextHover { */ public static final class PresenterControlCreator extends AbstractReusableInformationControlCreator { - private IWorkbenchSite fSite; + private final IWorkbenchSite fSite; /** * Creates a new PresenterControlCreator. @@ -544,6 +545,7 @@ public class JavadocHover extends AbstractJavaEditorTextHover { /** * @deprecated see {@link org.eclipse.jface.text.ITextHover#getHoverInfo(ITextViewer, IRegion)} */ + @Deprecated public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) { JavadocBrowserInformationControlInput info= (JavadocBrowserInformationControlInput) getHoverInfo2(textViewer, hoverRegion); return info != null ? info.getHtml() : null; @@ -585,11 +587,10 @@ public class JavadocHover extends AbstractJavaEditorTextHover { int leadingImageWidth= 0; if (nResults > 1) { - for (int i= 0; i < elements.length; i++) { HTMLPrinter.startBulletList(buffer); IJavaElement curr= elements[i]; - if (curr instanceof IMember || curr.getElementType() == IJavaElement.LOCAL_VARIABLE) { + if (curr instanceof IMember || curr instanceof IPackageFragment || curr.getElementType() == IJavaElement.LOCAL_VARIABLE) { String label= JavaElementLabels.getElementLabel(curr, getHeaderFlags(curr)); String link; try { @@ -608,44 +609,54 @@ public class JavadocHover extends AbstractJavaEditorTextHover { } else { element= elements[0]; - if (element instanceof IMember) { + if(element instanceof IPackageFragment){ + HTMLPrinter.addSmallHeader(buffer, getInfoText(element, editorInputElement, hoverRegion, true)); + buffer.append("<br>"); //$NON-NLS-1$ + IPackageFragment packge = (IPackageFragment)element; + Reader reader= null; + try { + String content= JavadocContentAccess2.getHTMLContent(packge); + IPackageFragmentRoot root= (IPackageFragmentRoot) packge.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); + boolean isBinary= (root.getKind() == IPackageFragmentRoot.K_BINARY); + if (content != null) { + base= JavaDocLocations.getBaseURL(element, isBinary); + reader= new StringReader(content); + } else { + String explanationForMissingJavadoc= JavaDocLocations.getExplanationForMissingJavadoc(element, root); + if(explanationForMissingJavadoc != null) + reader= new StringReader(explanationForMissingJavadoc); + } + } catch (CoreException e) { + reader= new StringReader(JavaHoverMessages.JavadocHover_error_gettingJavadoc); + JavaPlugin.log(e); + } + if(reader != null){ + HTMLPrinter.addParagraph(buffer, reader); + } + hasContents= true; + } else if (element instanceof IMember) { HTMLPrinter.addSmallHeader(buffer, getInfoText(element, editorInputElement, hoverRegion, true)); buffer.append("<br>"); //$NON-NLS-1$ addAnnotations(buffer, element, editorInputElement, hoverRegion); IMember member= (IMember) element; - Reader reader; + Reader reader= null; try { -// reader= JavadocContentAccess.getHTMLContentReader(member, true, true); + IPackageFragmentRoot root= (IPackageFragmentRoot) member.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); String content= JavadocContentAccess2.getHTMLContent(member, true); - reader= content == null ? null : new StringReader(content); - - // Provide hint why there's no Javadoc - if (reader == null && member.isBinary()) { - boolean hasAttachedJavadoc= JavaDocLocations.getJavadocBaseLocation(member) != null; - IPackageFragmentRoot root= (IPackageFragmentRoot)member.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); - boolean hasAttachedSource= root != null && root.getSourceAttachmentPath() != null; - IOpenable openable= member.getOpenable(); - boolean hasSource= openable.getBuffer() != null; - - if (!hasAttachedSource && !hasAttachedJavadoc) - reader= new StringReader(JavaHoverMessages.JavadocHover_noAttachments); - else if (!hasAttachedJavadoc && !hasSource) - reader= new StringReader(JavaHoverMessages.JavadocHover_noAttachedJavadoc); - else if (!hasAttachedSource) - reader= new StringReader(JavaHoverMessages.JavadocHover_noAttachedSource); - else if (!hasSource) - reader= new StringReader(JavaHoverMessages.JavadocHover_noInformation); - + boolean isBinary= member.isBinary(); + if (content != null) { + base= JavaDocLocations.getBaseURL(element, isBinary); + reader= new StringReader(content); } else { - base= JavaDocLocations.getBaseURL(member); + String explanationForMissingJavadoc= JavaDocLocations.getExplanationForMissingJavadoc(element, root); + if(explanationForMissingJavadoc != null) + reader= new StringReader(explanationForMissingJavadoc); } - } catch (JavaModelException ex) { reader= new StringReader(JavaHoverMessages.JavadocHover_error_gettingJavadoc); JavaPlugin.log(ex); } - - if (reader != null) { + if(reader != null){ HTMLPrinter.addParagraph(buffer, reader); } hasContents= true; @@ -716,6 +727,8 @@ public class JavadocHover extends AbstractJavaEditorTextHover { return LOCAL_VARIABLE_FLAGS; case IJavaElement.TYPE_PARAMETER: return TYPE_PARAMETER_FLAGS; + case IJavaElement.PACKAGE_FRAGMENT: + return LABEL_FLAGS ^ JavaElementLabels.ALL_FULLY_QUALIFIED; default: return LABEL_FLAGS; } diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/javadoc/JavadocContentAccess2.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/javadoc/JavadocContentAccess2.java index 45d7273b74..0729d6d309 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/javadoc/JavadocContentAccess2.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/javadoc/JavadocContentAccess2.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2012 IBM Corporation and others. + * Copyright (c) 2008, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -11,7 +11,11 @@ *******************************************************************************/ package org.eclipse.jdt.internal.ui.text.javadoc; +import java.io.BufferedReader; +import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.io.Reader; import java.net.URISyntaxException; import java.net.URL; @@ -23,22 +27,45 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; + +import org.eclipse.core.filebuffers.FileBuffers; +import org.eclipse.core.filebuffers.ITextFileBuffer; +import org.eclipse.core.filebuffers.ITextFileBufferManager; +import org.eclipse.core.filebuffers.LocationKind; import org.eclipse.jface.internal.text.html.HTMLPrinter; import org.eclipse.jdt.core.IBuffer; +import org.eclipse.jdt.core.IClassFile; +import org.eclipse.jdt.core.IClasspathAttribute; +import org.eclipse.jdt.core.IClasspathEntry; +import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IField; +import org.eclipse.jdt.core.IJarEntryResource; +import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.core.IMethod; +import org.eclipse.jdt.core.IPackageDeclaration; +import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.ISourceRange; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.ITypeHierarchy; +import org.eclipse.jdt.core.ITypeRoot; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.Signature; @@ -46,6 +73,7 @@ import org.eclipse.jdt.core.SourceRange; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; +import org.eclipse.jdt.core.dom.Comment; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.IBinding; import org.eclipse.jdt.core.dom.IVariableBinding; @@ -453,7 +481,7 @@ public class JavadocContentAccess2 { * if there's no source * @return the Javadoc comment content in HTML or <code>null</code> if the member * does not have a Javadoc comment or if no source is available - * @throws JavaModelException is thrown when the element's Javadoc can not be accessed + * @throws JavaModelException is thrown when the element's Javadoc cannot be accessed */ public static String getHTMLContent(IMember member, boolean useAttachedJavadoc) throws JavaModelException { String sourceJavadoc= getHTMLContentFromSource(member); @@ -576,23 +604,12 @@ public class JavadocContentAccess2 { return javadoc2HTML(member, rawJavadoc); } - private static Javadoc getJavadocNode(IMember member, String rawJavadoc) { + private static Javadoc getJavadocNode(IJavaElement element, String rawJavadoc) { //FIXME: take from SharedASTProvider if available //Caveat: Javadoc nodes are not available when Javadoc processing has been disabled! //https://bugs.eclipse.org/bugs/show_bug.cgi?id=212207 - ASTParser parser= ASTParser.newParser(ASTProvider.SHARED_AST_LEVEL); - - IJavaProject javaProject= member.getJavaProject(); - parser.setProject(javaProject); - Map<String, String> options= javaProject.getOptions(true); - options.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED); // workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=212207 - parser.setCompilerOptions(options); - - String source= rawJavadoc + "class C{}"; //$NON-NLS-1$ - parser.setSource(source.toCharArray()); - - CompilationUnit root= (CompilationUnit) parser.createAST(null); + CompilationUnit root= createAST(element, rawJavadoc); if (root == null) return null; List<AbstractTypeDeclaration> types= root.types(); @@ -602,17 +619,27 @@ public class JavadocContentAccess2 { return type.getJavadoc(); } + private static String javadoc2HTML(IMember member, String rawJavadoc) { Javadoc javadoc= getJavadocNode(member, rawJavadoc); if (javadoc == null) { + Reader contentReader= null; // fall back to JavadocContentAccess: try { - Reader contentReader= JavadocContentAccess.getHTMLContentReader(member, false, false); + contentReader= JavadocContentAccess.getHTMLContentReader(member, false, false); if (contentReader != null) return getString(contentReader); } catch (JavaModelException e) { JavaPlugin.log(e); + }finally{ + if(contentReader != null){ + try { + contentReader.close(); + } catch (IOException e) { + //ignore + } + } } return null; } @@ -1597,4 +1624,333 @@ public class JavadocContentAccess2 { return true; } + /** + * Returns the Javadoc for a PackageDeclaration. + * + * @param packageDeclaration the Java element whose Javadoc has to be retrieved + * @return the package documentation in HTML format or <code>null</code> if there is no + * associated Javadoc + * @throws CoreException if the Java element does not exists or an exception occurs while + * accessing the file containing the package Javadoc + * @since 3.9 + */ + public static String getHTMLContent(IPackageDeclaration packageDeclaration) throws CoreException { + IJavaElement element= packageDeclaration.getAncestor(IJavaElement.PACKAGE_FRAGMENT); + if (element instanceof IPackageFragment) { + return getHTMLContent((IPackageFragment) element); + } + return null; + } + + + /** + * Returns the Javadoc for a package which could be present in package.html, package-info.java + * or from an attached Javadoc. + * + * @param packageFragment the package which is requesting for the document + * @return the document content in HTML format or <code>null</code> if there is no associated + * Javadoc + * @throws CoreException if the Java element does not exists or an exception occurs while + * accessing the file containing the package Javadoc + * @since 3.9 + */ + public static String getHTMLContent(IPackageFragment packageFragment) throws CoreException { + CompilationUnit astNode= null; + IPackageFragmentRoot root= (IPackageFragmentRoot) packageFragment.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); + + //1==> Handle the case when the documentation is present in package-info.java or package-info.class file + ITypeRoot typeRoot= null; + boolean isBinary= root.getKind() == IPackageFragmentRoot.K_BINARY; + if (isBinary) { + typeRoot= packageFragment.getClassFile(JavaModelUtil.PACKAGE_INFO_CLASS); + } else { + typeRoot= packageFragment.getCompilationUnit(JavaModelUtil.PACKAGE_INFO_JAVA); + } + if (typeRoot != null && typeRoot.exists()) { + String source= typeRoot.getSource(); + //the source can be null for some of the class files + if (source != null) { + astNode= createAST(typeRoot); + if (astNode != null) { + List<Comment> commentList= astNode.getCommentList(); + if (commentList != null && !commentList.isEmpty()) { + for (int i= commentList.size() - 1; i >= 0; i--) { + Comment comment= commentList.get(i); + if (comment instanceof Javadoc) { + JavadocContentAccess2 docacc= new JavadocContentAccess2(null, (Javadoc) comment, source); + return docacc.toHTML(); + } + } + } + } + } + } + + // 2==> Handle the case when the documentation is done in package.html file. The file can be either in normal source folder or coming from a jar file + else { + Object[] nonJavaResources= packageFragment.getNonJavaResources(); + // 2.1 ==>If the package.html file is present in the source or directly in the binary jar + for (Object nonJavaResource : nonJavaResources) { + if (nonJavaResource instanceof IFile) { + IFile iFile= (IFile) nonJavaResource; + if (iFile.exists() && JavaModelUtil.PACKAGE_HTML.equals(iFile.getName())) { + return getIFileContent(iFile); + } + } + } + + // 2.2==>The file is present in a binary container + if (isBinary) { + for (Object nonJavaResource : nonJavaResources) { + // The content is from an external binary class folder + if (nonJavaResource instanceof IJarEntryResource) { + IJarEntryResource jarEntryResource= (IJarEntryResource) nonJavaResource; + String encoding= getSourceAttachmentEncoding(root); + if (JavaModelUtil.PACKAGE_HTML.equals(jarEntryResource.getName()) && jarEntryResource.isFile()) { + return getHTMLContent(jarEntryResource, encoding); + } + } + } + //2.3 ==>The file is present in the source attachment path. + String contents= getHTMLContentFromAttachedSource(root, packageFragment); + if (contents != null) + return contents; + } + } + + //3==> Handle the case when the documentation is coming from the attached Javadoc + if ((root.isArchive() || root.isExternal())) { + return packageFragment.getAttachedJavadoc(null); + + } + + return null; + } + + + private static String getHTMLContent(IJarEntryResource jarEntryResource, String encoding) throws CoreException { + InputStream in= jarEntryResource.getContents(); + try { + return getContentsFromInputStream(in, encoding); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + //ignore + } + } + } + } + + private static String getHTMLContentFromAttachedSource(IPackageFragmentRoot root, IPackageFragment packageFragment) throws CoreException { + String packagePath= packageFragment.getElementName().replace(".", "/") + "/" + JavaModelUtil.PACKAGE_HTML; //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$ + IPath sourceAttachmentPath= root.getSourceAttachmentPath(); + if (sourceAttachmentPath != null) { + File file= sourceAttachmentPath.toFile(); + if (file.isDirectory()) { + //the path could be an absolute path to the source folder + IPath packagedocPath= sourceAttachmentPath.append(packagePath); + if (packagedocPath.toFile().exists()) + return getFileContent(packagedocPath.toFile()); + + } else { + if (!file.exists()) { + //the path could be a workspace relative path to a jar or to the source folder + IWorkspaceRoot wsRoot= ResourcesPlugin.getWorkspace().getRoot(); + IResource res= wsRoot.findMember(sourceAttachmentPath.append(packagePath)); + if (res == null) + res= wsRoot.findMember(sourceAttachmentPath); + + if (res != null) + file= res.getLocation().toFile(); + + } + if (file.exists()) { + if (JavaModelUtil.PACKAGE_HTML.equals(file.getName())) + return getFileContent(file); + + //the package documentation could be in a Jar/Zip + IPath sourceAttachmentRootPath= root.getSourceAttachmentRootPath(); + String packagedocPath; + //consider the root path also in the search path if it exists + if (sourceAttachmentRootPath != null) { + packagedocPath= sourceAttachmentRootPath.append(packagePath).toOSString(); + } else { + packagedocPath= packagePath; + } + ZipFile zipFile= null; + InputStream in= null; + try { + zipFile= new ZipFile(file, ZipFile.OPEN_READ); + ZipEntry packageHtml= zipFile.getEntry(packagedocPath); + if (packageHtml != null) { + in= zipFile.getInputStream(packageHtml); + String encoding= getSourceAttachmentEncoding(root); + return getContentsFromInputStream(in, encoding); + } + } catch (IOException e) { + throw new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), e.getMessage(), e)); + } finally { + try { + if (in != null) { + in.close(); + } + } catch (IOException e) { + //ignore + } + try { + if (zipFile != null) { + zipFile.close();//this will close the InputStream also + } + } catch (IOException e) { + //ignore + } + } + } + } + } + + return null; + } + + + private static String getContentsFromInputStream(InputStream in, String encoding) throws CoreException { + final int defaultFileSize= 15 * 1024; + StringBuffer buffer= new StringBuffer(defaultFileSize); + Reader reader= null; + + try { + reader= new BufferedReader(new InputStreamReader(in, encoding), defaultFileSize); + + char[] readBuffer= new char[2048]; + int charCount= reader.read(readBuffer); + + while (charCount > 0) { + buffer.append(readBuffer, 0, charCount); + charCount= reader.read(readBuffer); + } + + } catch (IOException e) { + throw new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), e.getMessage(), e)); + } finally { + try { + if (reader != null) { + reader.close();//this will also close the InputStream wrapped in the reader + } + } catch (IOException e) { + //ignore + } + } + return buffer.toString(); + } + + + private static String getSourceAttachmentEncoding(IPackageFragmentRoot root) throws JavaModelException { + String encoding= ResourcesPlugin.getEncoding(); + IClasspathEntry entry= root.getRawClasspathEntry(); + + if (entry != null) { + int kind= entry.getEntryKind(); + if (kind == IClasspathEntry.CPE_LIBRARY || kind == IClasspathEntry.CPE_VARIABLE) { + IClasspathAttribute[] extraAttributes= entry.getExtraAttributes(); + for (int i= 0; i < extraAttributes.length; i++) { + IClasspathAttribute attrib= extraAttributes[i]; + if (IClasspathAttribute.SOURCE_ATTACHMENT_ENCODING.equals(attrib.getName())) { + return attrib.getValue(); + } + } + } + } + + return encoding; + } + + /** + * Reads a compilation unit and creates the AST DOM for manipulating the Java source. + * + * @param typeRoot cane be a compilation unit or a class file + * @return parsed compilation unit + */ + + private static CompilationUnit createAST(ITypeRoot typeRoot) { + ASTParser parser= createASTParser(typeRoot); + parser.setKind(ASTParser.K_COMPILATION_UNIT); + if (typeRoot instanceof ICompilationUnit) { + parser.setSource((ICompilationUnit) typeRoot); + } else if (typeRoot instanceof IClassFile) { + parser.setSource((IClassFile) typeRoot); + } + parser.setResolveBindings(true); + return (CompilationUnit) parser.createAST(null); + + } + + + private static CompilationUnit createAST(IJavaElement element, String rawJavadoc) { + ASTParser parser= createASTParser(element); + String source= rawJavadoc + "class C{}"; //$NON-NLS-1$ + parser.setSource(source.toCharArray()); + return (CompilationUnit) parser.createAST(null); + } + + private static ASTParser createASTParser(IJavaElement element) { + ASTParser parser= ASTParser.newParser(ASTProvider.SHARED_AST_LEVEL); + IJavaProject javaProject= element.getJavaProject(); + parser.setProject(javaProject); + Map<String, String> options= javaProject.getOptions(true); + options.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED); // workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=212207 + parser.setCompilerOptions(options); + return parser; + } + + /** + * Reads the content of the IFile. + * + * @param file the file whose content has to be read + * @return the content of the file + * @throws CoreException if the file could not be successfully connected or disconnected + */ + private static String getIFileContent(IFile file) throws CoreException { + String content= null; + ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager(); + IPath fullPath= file.getFullPath(); + manager.connect(fullPath, LocationKind.IFILE, null); + try { + ITextFileBuffer buffer= manager.getTextFileBuffer(fullPath, LocationKind.IFILE); + if (buffer != null) { + content= buffer.getDocument().get(); + } + } finally { + manager.disconnect(fullPath, LocationKind.IFILE, null); + } + + return content; + } + + + /** + * Reads the content of the java.io.File. + * + * @param file the file whose content has to be read + * @return the content of the file + * @throws CoreException if the file could not be successfully connected or disconnected + */ + private static String getFileContent(File file) throws CoreException { + String content= null; + ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager(); + + IPath fullPath= new Path(file.getAbsolutePath()); + manager.connect(fullPath, LocationKind.LOCATION, null); + try { + ITextFileBuffer buffer= manager.getTextFileBuffer(fullPath, LocationKind.LOCATION); + if (buffer != null) { + content= buffer.getDocument().get(); + } + } finally { + manager.disconnect(fullPath, LocationKind.LOCATION, null); + } + return content; + } + } diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/NewPackageCreationWizard.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/NewPackageCreationWizard.java index d2afb4b707..00e1466b20 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/NewPackageCreationWizard.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/NewPackageCreationWizard.java @@ -75,7 +75,7 @@ public class NewPackageCreationWizard extends NewElementWizard { if (res) { IResource resource= fPage.getModifiedResource(); selectAndReveal(resource); - if (resource instanceof IFile && resource.getName().equals(JavaModelUtil.PACKAGE_INFO_JAVA)) { + if (resource instanceof IFile && JavaModelUtil.PACKAGE_INFO_JAVA.equals(resource.getName())) { openResource((IFile) resource); } } diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/text/java/CompletionProposalCollector.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/text/java/CompletionProposalCollector.java index ccd34ac8f9..eb3ec760d1 100755 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/text/java/CompletionProposalCollector.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/text/java/CompletionProposalCollector.java @@ -55,6 +55,7 @@ import org.eclipse.jdt.internal.ui.text.java.JavaFieldWithCastedReceiverCompleti import org.eclipse.jdt.internal.ui.text.java.JavaMethodCompletionProposal; import org.eclipse.jdt.internal.ui.text.java.LazyJavaCompletionProposal; import org.eclipse.jdt.internal.ui.text.java.LazyJavaTypeCompletionProposal; +import org.eclipse.jdt.internal.ui.text.java.LazyPackageCompletionProposal; import org.eclipse.jdt.internal.ui.text.java.MethodDeclarationCompletionProposal; import org.eclipse.jdt.internal.ui.text.java.MethodProposalInfo; import org.eclipse.jdt.internal.ui.text.java.OverrideCompletionProposal; @@ -843,14 +844,7 @@ public class CompletionProposalCollector extends CompletionRequestor { } private IJavaCompletionProposal createPackageProposal(CompletionProposal proposal) { - String completion= String.valueOf(proposal.getCompletion()); - int start= proposal.getReplaceStart(); - int length= getLength(proposal); - StyledString label= fLabelProvider.createSimpleLabel(proposal); - Image image= getImage(fLabelProvider.createPackageImageDescriptor(proposal)); - int relevance= computeRelevance(proposal); - - return new JavaCompletionProposal(completion, start, length, image, label, relevance); + return new LazyPackageCompletionProposal(proposal, getInvocationContext()); } private IJavaCompletionProposal createTypeProposal(CompletionProposal typeProposal) { diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/wizards/NewPackageWizardPage.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/wizards/NewPackageWizardPage.java index c74f41056d..537df59df3 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/wizards/NewPackageWizardPage.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/wizards/NewPackageWizardPage.java @@ -102,7 +102,7 @@ public class NewPackageWizardPage extends NewContainerWizardPage { private static final String PACKAGE_INFO_JAVA_FILENAME= JavaModelUtil.PACKAGE_INFO_JAVA; - private static final String PACKAGE_HTML_FILENAME= "package.html"; //$NON-NLS-1$ + private static final String PACKAGE_HTML_FILENAME= JavaModelUtil.PACKAGE_HTML; private static final String PAGE_NAME= "NewPackageWizardPage"; //$NON-NLS-1$ |