diff --git a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocExternalFilter.java b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocExternalFilter.java index b2da6749b317..92bfe67d6f5f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocExternalFilter.java +++ b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocExternalFilter.java @@ -19,15 +19,19 @@ import com.intellij.codeInsight.documentation.AbstractExternalFilter; import com.intellij.codeInsight.documentation.DocumentationManager; import com.intellij.codeInsight.documentation.PlatformDocumentationUtil; import com.intellij.ide.BrowserUtil; +import com.intellij.lang.java.JavaDocumentationProvider; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.NullableComputable; +import com.intellij.openapi.util.Trinity; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; import com.intellij.psi.search.GlobalSearchScope; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.regex.Matcher; @@ -43,7 +47,13 @@ import java.util.regex.Pattern; public class JavaDocExternalFilter extends AbstractExternalFilter { private final Project myProject; - + + private static final Trinity ourPackageInfoSettings = Trinity.create( + Pattern.compile("package\\s+[^\\s]+\\s+description", Pattern.CASE_INSENSITIVE), + Pattern.compile("START OF BOTTOM NAVBAR", Pattern.CASE_INSENSITIVE), + Boolean.TRUE + ); + protected static @NonNls final Pattern ourHTMLsuffix = Pattern.compile("[.][hH][tT][mM][lL]?"); protected static @NonNls final Pattern ourParentFolderprefix = Pattern.compile("^[.][.]/"); protected static @NonNls final Pattern ourAnchorsuffix = Pattern.compile("#(.*)$"); @@ -110,9 +120,11 @@ public class JavaDocExternalFilter extends AbstractExternalFilter { if (externalDoc != null) { if (element instanceof PsiMethod) { final String className = ApplicationManager.getApplication().runReadAction( - new Computable() { + new NullableComputable() { + @Nullable public String compute() { - return ((PsiMethod) element).getContainingClass().getQualifiedName(); + PsiClass aClass = ((PsiMethod)element).getContainingClass(); + return aClass == null ? null : aClass.getQualifiedName(); } } ); @@ -126,4 +138,9 @@ public class JavaDocExternalFilter extends AbstractExternalFilter { return externalDoc; } + @NotNull + @Override + protected Trinity getParseSettings(@NotNull String url) { + return url.endsWith(JavaDocumentationProvider.PACKAGE_SUMMARY_FILE) ? ourPackageInfoSettings : super.getParseSettings(url); + } } diff --git a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java index e09a0bed531f..a06f8fa44871 100644 --- a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java +++ b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java @@ -26,6 +26,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.impl.JavaConstantExpressionEvaluator; diff --git a/java/java-tests/testData/codeInsight/externalJavadoc/packageSummary/util/expected.html b/java/java-tests/testData/codeInsight/externalJavadoc/packageSummary/util/expected.html new file mode 100644 index 000000000000..51cd5dd49edd --- /dev/null +++ b/java/java-tests/testData/codeInsight/externalJavadoc/packageSummary/util/expected.html @@ -0,0 +1,38 @@ +

Package java.util Description

+
Contains the collections framework, legacy collection classes, event model, + date and time facilities, internationalization, and miscellaneous utility + classes (a string tokenizer, a random-number generator, and a bit array). + +

Package Specification

+ + +

Related Documentation

+ For overviews, tutorials, examples, guides, and tool documentation, please see: +
+
Since:
+
JDK1.0
+ + \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/externalJavadoc/packageSummary/util/page.html b/java/java-tests/testData/codeInsight/externalJavadoc/packageSummary/util/page.html new file mode 100644 index 000000000000..87c085816fcd --- /dev/null +++ b/java/java-tests/testData/codeInsight/externalJavadoc/packageSummary/util/page.html @@ -0,0 +1,896 @@ + + + + + + + java.util (Java Platform SE 7 ) + + + + + + + + +
+ + + + + +
Java™ Platform
Standard Ed. 7
+
+ + +
+

Package java.util

+
+
Contains the collections framework, legacy collection classes, event model, + date and time facilities, internationalization, and miscellaneous utility + classes (a string tokenizer, a random-number generator, and a bit array).
+
+

See: Description

+
+
+
    +
  • + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Interface Summary 
    InterfaceDescription
    Collection<E> +
    The root interface in the collection hierarchy.
    +
    Comparator<T> +
    A comparison function, which imposes a total ordering on some + collection of objects.
    +
    Deque<E> +
    A linear collection that supports element insertion and removal at + both ends.
    +
    Enumeration<E> +
    An object that implements the Enumeration interface generates a + series of elements, one at a time.
    +
    EventListener +
    A tagging interface that all event listener interfaces must extend.
    +
    Formattable +
    The Formattable interface must be implemented by any class that + needs to perform custom formatting using the 's' conversion + specifier of Formatter.
    +
    Iterator<E> +
    An iterator over a collection.
    +
    List<E> +
    An ordered collection (also known as a sequence).
    +
    ListIterator<E> +
    An iterator for lists that allows the programmer + to traverse the list in either direction, modify + the list during iteration, and obtain the iterator's + current position in the list.
    +
    Map<K,V> +
    An object that maps keys to values.
    +
    Map.Entry<K,V> +
    A map entry (key-value pair).
    +
    NavigableMap<K,V> +
    A SortedMap extended with navigation methods returning the + closest matches for given search targets.
    +
    NavigableSet<E> +
    A SortedSet extended with navigation methods reporting + closest matches for given search targets.
    +
    Observer +
    A class can implement the Observer interface when it + wants to be informed of changes in observable objects.
    +
    Queue<E> +
    A collection designed for holding elements prior to processing.
    +
    RandomAccess +
    Marker interface used by List implementations to indicate that + they support fast (generally constant time) random access.
    +
    Set<E> +
    A collection that contains no duplicate elements.
    +
    SortedMap<K,V> +
    A Map that further provides a total ordering on its keys.
    +
    SortedSet<E> +
    A Set that further provides a total ordering on its elements.
    +
    +
  • +
  • + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Class Summary 
    ClassDescription
    AbstractCollection<E> +
    This class provides a skeletal implementation of the Collection + interface, to minimize the effort required to implement this interface.
    +
    AbstractList<E> +
    This class provides a skeletal implementation of the List + interface to minimize the effort required to implement this interface + backed by a "random access" data store (such as an array).
    +
    AbstractMap<K,V> +
    This class provides a skeletal implementation of the Map + interface, to minimize the effort required to implement this interface.
    +
    AbstractMap.SimpleEntry<K,V> +
    An Entry maintaining a key and a value.
    +
    AbstractMap.SimpleImmutableEntry<K,V> +
    An Entry maintaining an immutable key and value.
    +
    AbstractQueue<E> +
    This class provides skeletal implementations of some Queue + operations.
    +
    AbstractSequentialList<E> +
    This class provides a skeletal implementation of the List + interface to minimize the effort required to implement this interface + backed by a "sequential access" data store (such as a linked list).
    +
    AbstractSet<E> +
    This class provides a skeletal implementation of the Set + interface to minimize the effort required to implement this + interface.
    +
    ArrayDeque<E> +
    Resizable-array implementation of the Deque interface.
    +
    ArrayList<E> +
    Resizable-array implementation of the List interface.
    +
    Arrays +
    This class contains various methods for manipulating arrays (such as + sorting and searching).
    +
    BitSet +
    This class implements a vector of bits that grows as needed.
    +
    Calendar +
    The Calendar class is an abstract class that provides methods + for converting between a specific instant in time and a set of calendar fields such as YEAR, MONTH, + DAY_OF_MONTH, HOUR, and so on, and for + manipulating the calendar fields, such as getting the date of the next + week.
    +
    Collections +
    This class consists exclusively of static methods that operate on or return + collections.
    +
    Currency +
    Represents a currency.
    +
    Date +
    The class Date represents a specific instant + in time, with millisecond precision.
    +
    Dictionary<K,V> +
    The Dictionary class is the abstract parent of any + class, such as Hashtable, which maps keys to values.
    +
    EnumMap<K extends Enum<K>,V> +
    A specialized Map implementation for use with enum type keys.
    +
    EnumSet<E extends Enum<E>> +
    A specialized Set implementation for use with enum types.
    +
    EventListenerProxy<T extends EventListener> +
    An abstract wrapper class for an EventListener class + which associates a set of additional parameters with the listener.
    +
    EventObject +
    + The root class from which all event state objects shall be derived.
    +
    FormattableFlags +
    FomattableFlags are passed to the Formattable.formatTo() method and modify the output format for Formattables.
    +
    Formatter +
    An interpreter for printf-style format strings.
    +
    GregorianCalendar +
    GregorianCalendar is a concrete subclass of + Calendar and provides the standard calendar system + used by most of the world.
    +
    HashMap<K,V> +
    Hash table based implementation of the Map interface.
    +
    HashSet<E> +
    This class implements the Set interface, backed by a hash table + (actually a HashMap instance).
    +
    Hashtable<K,V> +
    This class implements a hash table, which maps keys to values.
    +
    IdentityHashMap<K,V> +
    This class implements the Map interface with a hash table, using + reference-equality in place of object-equality when comparing keys (and + values).
    +
    LinkedHashMap<K,V> +
    Hash table and linked list implementation of the Map interface, + with predictable iteration order.
    +
    LinkedHashSet<E> +
    Hash table and linked list implementation of the Set interface, + with predictable iteration order.
    +
    LinkedList<E> +
    Doubly-linked list implementation of the List and Deque + interfaces.
    +
    ListResourceBundle +
    ListResourceBundle is an abstract subclass of + ResourceBundle that manages resources for a locale + in a convenient and easy to use list.
    +
    Locale +
    A Locale object represents a specific geographical, political, + or cultural region.
    +
    Locale.Builder +
    Builder is used to build instances of Locale + from values configured by the setters.
    +
    Objects +
    This class consists of static utility methods for operating + on objects.
    +
    Observable +
    This class represents an observable object, or "data" + in the model-view paradigm.
    +
    PriorityQueue<E> +
    An unbounded priority queue based on a priority heap.
    +
    Properties +
    The Properties class represents a persistent set of + properties.
    +
    PropertyPermission +
    This class is for property permissions.
    +
    PropertyResourceBundle +
    PropertyResourceBundle is a concrete subclass of + ResourceBundle that manages resources for a locale + using a set of static strings from a property file.
    +
    Random +
    An instance of this class is used to generate a stream of + pseudorandom numbers.
    +
    ResourceBundle +
    Resource bundles contain locale-specific objects.
    +
    ResourceBundle.Control +
    ResourceBundle.Control defines a set of callback methods + that are invoked by the ResourceBundle.getBundle factory + methods during the bundle loading process.
    +
    Scanner +
    A simple text scanner which can parse primitive types and strings using + regular expressions.
    +
    ServiceLoader<S> +
    A simple service-provider loading facility.
    +
    SimpleTimeZone +
    SimpleTimeZone is a concrete subclass of TimeZone + that represents a time zone for use with a Gregorian calendar.
    +
    Stack<E> +
    The Stack class represents a last-in-first-out + (LIFO) stack of objects.
    +
    StringTokenizer +
    The string tokenizer class allows an application to break a + string into tokens.
    +
    Timer +
    A facility for threads to schedule tasks for future execution in a + background thread.
    +
    TimerTask +
    A task that can be scheduled for one-time or repeated execution by a Timer.
    +
    TimeZone +
    TimeZone represents a time zone offset, and also figures out daylight + savings.
    +
    TreeMap<K,V> +
    A Red-Black tree based NavigableMap implementation.
    +
    TreeSet<E> +
    A NavigableSet implementation based on a TreeMap.
    +
    UUID +
    A class that represents an immutable universally unique identifier (UUID).
    +
    Vector<E> +
    The Vector class implements a growable array of + objects.
    +
    WeakHashMap<K,V> +
    Hash table based implementation of the Map interface, with + weak keys.
    +
    +
  • +
  • + + + + + + + + + + + + + + + + +
    Enum Summary 
    EnumDescription
    Formatter.BigDecimalLayoutForm 
    Locale.Category +
    Enum for locale categories.
    +
    +
  • +
  • + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Exception Summary 
    ExceptionDescription
    ConcurrentModificationException +
    This exception may be thrown by methods that have detected concurrent + modification of an object when such modification is not permissible.
    +
    DuplicateFormatFlagsException +
    Unchecked exception thrown when duplicate flags are provided in the format + specifier.
    +
    EmptyStackException +
    Thrown by methods in the Stack class to indicate + that the stack is empty.
    +
    FormatFlagsConversionMismatchException +
    Unchecked exception thrown when a conversion and flag are incompatible.
    +
    FormatterClosedException +
    Unchecked exception thrown when the formatter has been closed.
    +
    IllegalFormatCodePointException +
    Unchecked exception thrown when a character with an invalid Unicode code + point as defined by Character.isValidCodePoint(int) is passed to the + Formatter.
    +
    IllegalFormatConversionException +
    Unchecked exception thrown when the argument corresponding to the format + specifier is of an incompatible type.
    +
    IllegalFormatException +
    Unchecked exception thrown when a format string contains an illegal syntax + or a format specifier that is incompatible with the given arguments.
    +
    IllegalFormatFlagsException +
    Unchecked exception thrown when an illegal combination flags is given.
    +
    IllegalFormatPrecisionException +
    Unchecked exception thrown when the precision is a negative value other than + -1, the conversion does not support a precision, or the value is + otherwise unsupported.
    +
    IllegalFormatWidthException +
    Unchecked exception thrown when the format width is a negative value other + than -1 or is otherwise unsupported.
    +
    IllformedLocaleException +
    Thrown by methods in Locale and Locale.Builder to + indicate that an argument is not a well-formed BCP 47 tag.
    +
    InputMismatchException +
    Thrown by a Scanner to indicate that the token + retrieved does not match the pattern for the expected type, or + that the token is out of range for the expected type.
    +
    InvalidPropertiesFormatException +
    Thrown to indicate that an operation could not complete because + the input did not conform to the appropriate XML document type + for a collection of properties, as per the Properties + specification.
    +
    MissingFormatArgumentException +
    Unchecked exception thrown when there is a format specifier which does not + have a corresponding argument or if an argument index refers to an argument + that does not exist.
    +
    MissingFormatWidthException +
    Unchecked exception thrown when the format width is required.
    +
    MissingResourceException +
    Signals that a resource is missing.
    +
    NoSuchElementException +
    Thrown by the nextElement method of an + Enumeration to indicate that there are no more + elements in the enumeration.
    +
    TooManyListenersException +
    + The TooManyListenersException Exception is used as part of + the Java Event model to annotate and implement a unicast special case of + a multicast Event Source.
    +
    UnknownFormatConversionException +
    Unchecked exception thrown when an unknown conversion is given.
    +
    UnknownFormatFlagsException +
    Unchecked exception thrown when an unknown flag is given.
    +
    +
  • +
  • + + + + + + + + + + + + +
    Error Summary 
    ErrorDescription
    ServiceConfigurationError +
    Error thrown when something goes wrong while loading a service provider.
    +
    +
  • +
+ + + +

Package java.util Description

+
Contains the collections framework, legacy collection classes, event model, + date and time facilities, internationalization, and miscellaneous utility + classes (a string tokenizer, a random-number generator, and a bit array). + +

Package Specification

+ + +

Related Documentation

+ For overviews, tutorials, examples, guides, and tool documentation, please see: +
+
Since:
+
JDK1.0
+
+ +
+ + + + + +
Java™ Platform
Standard Ed. 7
+
+ + +

Submit a bug or feature
For further API reference and developer documentation, see Java SE Documentation. That documentation contains more detailed, developer-targeted descriptions, with conceptual overviews, definitions of terms, workarounds, and working code examples.
Copyright © 1993, 2012, Oracle and/or its affiliates. All rights reserved.

+ + + + + + + + + + + + diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/ExternalJavadocPresentationTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/ExternalJavadocPresentationTest.java index 2673f4a78e0f..6fea5551e5f4 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/ExternalJavadocPresentationTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/ExternalJavadocPresentationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -39,7 +39,6 @@ public class ExternalJavadocPresentationTest extends LightCodeInsightTestCase { return JavaTestUtil.getJavaTestDataPath(); } - public void testStringClass() throws Exception { doTest("", "String/7/page.html", "String/7/expected.html"); doTest("", "String/6/page.html", "String/6/expected.html"); @@ -48,7 +47,11 @@ public class ExternalJavadocPresentationTest extends LightCodeInsightTestCase { public void testToLowerCase() throws Exception { doTest("lang/String.html#toLowerCase()", "String/7/page.html", "String/7/expectedToLowerCase.html"); doTest("lang/String.html#toLowerCase()", "String/6/page.html", "String/6/expectedToLowerCase.html"); - } + } + + public void testPackageSummary() throws Exception { + doTest("java/lang/package-summary.html", "packageSummary/util/page.html", "packageSummary/util/expected.html"); + } private void doTest(@NonNls String url, @NonNls String pageText, @NonNls String expected) throws Exception { final String basePath = getTestDataPath() + TEST_ROOT; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/AbstractExternalFilter.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/AbstractExternalFilter.java index 504ea5cdf8e6..7943c6b36958 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/AbstractExternalFilter.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/AbstractExternalFilter.java @@ -23,13 +23,18 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.util.ProgressIndicatorBase; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.Trinity; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtilRt; -import com.intellij.openapi.vfs.*; -import com.intellij.psi.*; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VfsUtilCore; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.psi.PsiElement; import com.intellij.util.io.UrlConnectionUtil; import com.intellij.util.net.HttpConfigurable; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.*; @@ -49,7 +54,11 @@ import java.util.regex.Pattern; public abstract class AbstractExternalFilter { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.javadoc.JavaDocExternalFilter"); - + + private static final Pattern ourClassDataStartPattern = Pattern.compile("START OF CLASS DATA", Pattern.CASE_INSENSITIVE); + private static final Pattern ourClassDataEndPattern = Pattern.compile("SUMMARY ========", Pattern.CASE_INSENSITIVE); + private static final Pattern ourNonClassDataEndPattern = Pattern.compile(" settings = getParseSettings(surl); + @NonNls Pattern startSection = settings.first; + @NonNls Pattern endSection = settings.second; + boolean useDt = settings.third; @NonNls String greatestEndSection = ""; - boolean isClassDoc = true; - - if (anchorMatcher.find()) { - isClassDoc = false; - startSection = "" + @@ -253,7 +256,7 @@ public abstract class AbstractExternalFilter { } } } - while (read != null && !StringUtilRt.toUpperCase(read).contains(startSection)); + while (read != null && !startSection.matcher(StringUtilRt.toUpperCase(read)).find()); if (input instanceof MyReader && contentEncoding != null) { if (contentEncoding != null && !contentEncoding.equals("UTF-8") && !contentEncoding.equals(((MyReader)input).getEncoding())) { //restart page parsing with correct encoding @@ -275,18 +278,15 @@ public abstract class AbstractExternalFilter { return; } - appendLine(data, read); - - if (isClassDoc) { + if (useDt) { boolean skip = false; - - while (((read = buf.readLine()) != null) && !StringUtilRt.toUpperCase(read).trim().equals(DL) && - !StringUtil.containsIgnoreCase(read, "
data.append(H2); skip = true; } - else if (StringUtil.indexOfIgnoreCase(read, greatestEndSection, 0) != -1) { + else if (endSection.matcher(read).find() || StringUtil.indexOfIgnoreCase(read, greatestEndSection, 0) != -1) { data.append(HTML_CLOSE); return; } @@ -294,6 +294,8 @@ public abstract class AbstractExternalFilter { appendLine(data, read); } } + while (((read = buf.readLine()) != null) && !StringUtilRt.toUpperCase(read).trim().equals(DL) && + !StringUtil.containsIgnoreCase(read, "
") && !StringUtil.containsIgnoreCase(read, "
  • ")) { appendLine(data, read); @@ -326,9 +331,32 @@ public abstract class AbstractExternalFilter { data.append(HTML_CLOSE); } + /** + * Decides what settings should be used for parsing content represented by the given url. + * + * @param url url which points to the target content + * @return following data: (start interested data boundary pattern; end interested data boundary pattern; + * replace table data by <dt>) + */ + @NotNull + protected Trinity getParseSettings(@NotNull String url) { + Pattern startSection = ourClassDataStartPattern; + Pattern endSection = ourClassDataEndPattern; + boolean useDt = true; + + Matcher anchorMatcher = ourAnchorsuffix.matcher(url); + if (anchorMatcher.find()) { + useDt = false; + startSection = Pattern.compile(Pattern.quote("