Index: lib/apichanges.xml =================================================================== RCS file: /cvs/editor/lib/apichanges.xml,v retrieving revision 1.9 diff -u -r1.9 apichanges.xml --- lib/apichanges.xml 22 Aug 2007 15:09:28 -0000 1.9 +++ lib/apichanges.xml 11 Sep 2007 14:23:45 -0000 @@ -82,6 +82,25 @@ + + Extending HyperlinkProviders + + + + + +

+ The hyperlink providers have been extended to allow: +

    +
  • tooltips for the hyperlinks
  • +
  • future extensions through HyperlinkType
  • +
+ + See newly added HyperlinkProviderExt class. +

+
+
+ Added BaseDocumentEvent.getChangeAttributes Index: lib/nbproject/project.properties =================================================================== RCS file: /cvs/editor/lib/nbproject/project.properties,v retrieving revision 1.21 diff -u -r1.21 project.properties --- lib/nbproject/project.properties 22 Aug 2007 15:09:30 -0000 1.21 +++ lib/nbproject/project.properties 11 Sep 2007 14:23:45 -0000 @@ -12,12 +12,12 @@ # "Portions Copyrighted [year] [name of copyright owner]" # # The Original Software is NetBeans. The Initial Developer of the Original -# Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun +# Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun # Microsystems, Inc. All Rights Reserved. javac.compilerargs=-Xlint:unchecked javac.source=1.5 -spec.version.base=1.17.0 +spec.version.base=1.18.0 is.autoload=true src.dir=../libsrc Index: libsrc/META-INF/services/org.netbeans.spi.editor.mimelookup.Class2LayerFolder =================================================================== RCS file: /cvs/editor/libsrc/META-INF/services/org.netbeans.spi.editor.mimelookup.Class2LayerFolder,v retrieving revision 1.1 diff -u -r1.1 org.netbeans.spi.editor.mimelookup.Class2LayerFolder --- libsrc/META-INF/services/org.netbeans.spi.editor.mimelookup.Class2LayerFolder 15 Apr 2007 23:08:52 -0000 1.1 +++ libsrc/META-INF/services/org.netbeans.spi.editor.mimelookup.Class2LayerFolder 11 Sep 2007 14:23:45 -0000 @@ -1 +1,2 @@ -org.netbeans.lib.editor.hyperlink.HyperlinkProviderManager \ No newline at end of file +org.netbeans.lib.editor.hyperlink.HyperlinkProviderManager +org.netbeans.lib.editor.hyperlink.HyperlinkProviderManagerExt Index: libsrc/org/netbeans/lib/editor/hyperlink/HyperlinkOperation.java =================================================================== RCS file: /cvs/editor/libsrc/org/netbeans/lib/editor/hyperlink/HyperlinkOperation.java,v retrieving revision 1.13 diff -u -r1.13 HyperlinkOperation.java --- libsrc/org/netbeans/lib/editor/hyperlink/HyperlinkOperation.java 15 Apr 2007 23:08:52 -0000 1.13 +++ libsrc/org/netbeans/lib/editor/hyperlink/HyperlinkOperation.java 11 Sep 2007 14:23:45 -0000 @@ -13,7 +13,7 @@ * "Portions Copyrighted [year] [name of copyright owner]" * * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun * Microsystems, Inc. All Rights Reserved. */ @@ -21,6 +21,8 @@ import java.awt.Color; import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Font; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; @@ -30,9 +32,16 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.Collection; +import java.util.EnumSet; +import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; +import javax.swing.ActionMap; +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JLabel; import javax.swing.SwingUtilities; +import javax.swing.UIManager; import javax.swing.text.BadLocationException; import javax.swing.text.Document; import javax.swing.text.JTextComponent; @@ -44,10 +53,15 @@ import org.netbeans.editor.EditorUI; import org.netbeans.editor.JumpList; import org.netbeans.editor.MarkFactory; +import org.netbeans.editor.PopupManager; import org.netbeans.editor.Settings; import org.netbeans.editor.SettingsNames; import org.netbeans.editor.Utilities; +import org.netbeans.editor.ext.ExtEditorUI; import org.netbeans.lib.editor.hyperlink.spi.HyperlinkProvider; +import org.netbeans.lib.editor.hyperlink.spi.HyperlinkProviderExt; +import org.netbeans.lib.editor.hyperlink.spi.HyperlinkType; +import org.openide.util.RequestProcessor; /** * @@ -57,8 +71,6 @@ private static Logger LOG = Logger.getLogger(HyperlinkOperation.class.getName()); - private static Cursor HAND_CURSOR = null; - private JTextComponent component; private Document currentDocument; private HyperlinkLayer layer; @@ -70,15 +82,117 @@ private boolean hyperlinkEnabled; private int actionKeyMask; + private HyperlinkProviderExt currentProvider; + private HyperlinkType currentType; + private int currentPosition; + private RequestProcessor.Task tooltip = new RequestProcessor("HyperlinkOperation").create(new Runnable() { + public void run() { + HyperlinkProviderExt provider; + HyperlinkType type; + Document doc; + int position; + + synchronized (HyperlinkOperation.this) { + provider = currentProvider; + type = currentType; + doc = currentDocument; + position = currentPosition; + } + + String desc = null; + + if (provider != null) { + desc = provider.getTooltipText(doc, position, type); + } + + synchronized (HyperlinkOperation.this) { + if (provider != currentProvider || type != currentType) + return ; + } + + final String descFinal = desc; + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + EditorUI ui = Utilities.getEditorUI(component); + + if (ui instanceof ExtEditorUI) { + ((ExtEditorUI) ui).getToolTipSupport().setToolTip(createLabelToolTip(descFinal)); + } + } + }); + } + }); + + private JLabel createLabelToolTip(String text) { + JLabel tt = new JLabel(text) { + public void setSize(int width, int height) { + Dimension prefSize = getPreferredSize(); + if (width > prefSize.width) { // given width unnecessarily big + width = prefSize.width; // shrink the width to preferred + if (height >= prefSize.height) { + height = prefSize.height; + } else { // height not big enough + height = -1; + } + } + + if (height >= 0) { // only for valid height + super.setSize(width, height); + } else { // signal that the height is too small to display tooltip + putClientProperty(PopupManager.Placement.class, null); + } + } + }; + + // bugfix of #43174 + tt.setActionMap(new ActionMap()); + tt.setInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null); + + final String UI_PREFIX = "ToolTip"; // NOI18N + + Font font = UIManager.getFont(UI_PREFIX + ".font"); // NOI18N + Color backColor = UIManager.getColor(UI_PREFIX + ".background"); // NOI18N + Color foreColor = UIManager.getColor(UI_PREFIX + ".foreground"); // NOI18N + + if (font != null) { + tt.setFont(font); + } + if (foreColor != null) { + tt.setForeground(foreColor); + } + if (backColor != null) { + tt.setBackground(backColor); + } + + tt.setOpaque(true); + tt.setBorder(BorderFactory.createCompoundBorder( + BorderFactory.createLineBorder(tt.getForeground()), + BorderFactory.createEmptyBorder(0, 3, 0, 3) + )); + + return tt; + } + + private static final int TOOLTIP_DELAY = 500; + public static HyperlinkOperation create(JTextComponent component, String mimeType) { return new HyperlinkOperation(component, mimeType); } - private static synchronized Cursor getHandCursor() { - if (HAND_CURSOR == null) - HAND_CURSOR = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); - - return HAND_CURSOR; + private static synchronized Cursor getMouseCursor(HyperlinkType type) { + switch (type) { + case GO_TO_DECLARATION: + return Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); + default: + throw new UnsupportedOperationException(); + } + } + + private static synchronized boolean isHyperlinkMouseCursor(Cursor c) { + return c == Cursor.getPredefinedCursor(Cursor.HAND_CURSOR) + || c == Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR) + || c == Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR); } /** Creates a new instance of HoveringImpl */ @@ -175,7 +289,11 @@ } public void mouseMoved(MouseEvent e) { - if (isHyperlinkEvent(e)) { + cancelTooltip(); + + HyperlinkType type = getHyperlinkType(e); + + if (type != null) { int position = component.viewToModel(e.getPoint()); if (position < 0) { @@ -184,35 +302,50 @@ return ; } - performHyperlinking(position); + performHyperlinking(position, type); } else { unHyperlink(true); } } public void mouseDragged(MouseEvent e) { - //ignored + cancelTooltip(); + } + + private synchronized void cancelTooltip() { + currentProvider = null; + currentType = null; + tooltip.cancel(); } - private boolean isHyperlinkEvent(InputEvent e) { - return ((e.getModifiers() | e.getModifiersEx()) & actionKeyMask) == actionKeyMask; + private synchronized void startTooltip(HyperlinkProviderExt provider, int position, HyperlinkType type) { + currentProvider = provider; + currentPosition = position; + currentType = type; + tooltip.schedule(TOOLTIP_DELAY); } - private void performHyperlinking(int position) { - HyperlinkProvider provider = findProvider(position); + private HyperlinkType getHyperlinkType(InputEvent e) { + return ((e.getModifiers() | e.getModifiersEx()) & actionKeyMask) == actionKeyMask ? HyperlinkType.GO_TO_DECLARATION : null; + } + + private void performHyperlinking(int position, HyperlinkType type) { + HyperlinkProviderExt provider = findProvider(position, type); if (provider != null) { - int[] offsets = provider.getHyperlinkSpan(component.getDocument(), position); + int[] offsets = provider.getHyperlinkSpan(component.getDocument(), position, type); - if (offsets != null) - makeHyperlink(offsets[0], offsets[1]); + if (offsets != null) { + makeHyperlink(type, offsets[0], offsets[1]); + startTooltip(provider, position, type); + } } else { unHyperlink(true); } } - private void performAction(int position) { - HyperlinkProvider provider = findProvider(position); + private void performAction(int position, HyperlinkType type) { + HyperlinkProviderExt provider = findProvider(position, type); if (provider != null) { unHyperlink(true); @@ -221,11 +354,11 @@ component.getCaret().setDot(position); JumpList.checkAddEntry(component, position); - provider.performClickAction(component.getDocument(), position); + provider.performClickAction(component.getDocument(), position, type); } } - private HyperlinkProvider findProvider(int position) { + private HyperlinkProviderExt findProvider(int position, HyperlinkType type) { Object mimeTypeObj = component.getDocument().getProperty("mimeType"); //NOI18N String mimeType; @@ -235,18 +368,42 @@ mimeType = this.mimeType; } + Collection extProviders = HyperlinkProviderManagerExt.getHyperlinkProviderExts(mimeType); + + for (HyperlinkProviderExt provider : extProviders) { + if (provider.getSupportedHyperlinkTypes().contains(type) && provider.isHyperlinkPoint(component.getDocument(), position, type)) { + return provider; + } + } + Collection providers = HyperlinkProviderManager.getHyperlinkProviders(mimeType); - for (HyperlinkProvider provider : providers) { + for (final HyperlinkProvider provider : providers) { if (provider.isHyperlinkPoint(component.getDocument(), position)) { - return provider; + return new HyperlinkProviderExt() { + public Set getSupportedHyperlinkTypes() { + return EnumSet.of(HyperlinkType.GO_TO_DECLARATION); + } + public boolean isHyperlinkPoint(Document doc, int offset, HyperlinkType type) { + return provider.isHyperlinkPoint(doc, offset); + } + public int[] getHyperlinkSpan(Document doc, int offset, HyperlinkType type) { + return provider.getHyperlinkSpan(doc, offset); + } + public void performClickAction(Document doc, int offset, HyperlinkType type) { + provider.performClickAction(doc, offset); + } + public String getTooltipText(Document doc, int offset, HyperlinkType type) { + return null; + } + }; } } return null; } - private synchronized void makeHyperlink(final int start, final int end) { + private synchronized void makeHyperlink(HyperlinkType type, final int start, final int end) { boolean makeCursorSnapshot = true; if (hyperlinkUp) { @@ -268,7 +425,7 @@ } else { oldComponentsMouseCursor = null; } - component.setCursor(getHandCursor()); + component.setCursor(getMouseCursor(type)); } } catch (BadLocationException e) { LOG.log(Level.WARNING, null, e); @@ -292,6 +449,7 @@ }); } } + private synchronized void unHyperlink(boolean removeCursor) { if (!hyperlinkUp) return ; @@ -305,7 +463,7 @@ damageRange(start, end); if (removeCursor) { - if (component.isCursorSet() && component.getCursor() == getHandCursor()) { + if (component.isCursorSet() && isHyperlinkMouseCursor(component.getCursor())) { component.setCursor(oldComponentsMouseCursor); } oldComponentsMouseCursor = null; @@ -320,43 +478,48 @@ } public void keyTyped(KeyEvent e) { - //ignored + cancelTooltip(); } public void keyReleased(KeyEvent e) { + cancelTooltip(); if ((e.getModifiers() & actionKeyMask) == 0) unHyperlink(true); } public void keyPressed(KeyEvent e) { - //ignored + cancelTooltip(); } public void mouseReleased(MouseEvent e) { - //ignored + cancelTooltip(); } public void mousePressed(MouseEvent e) { - //ignored + cancelTooltip(); } public void mouseExited(MouseEvent e) { - //ignored + cancelTooltip(); } public void mouseEntered(MouseEvent e) { - //ignored + cancelTooltip(); } public void mouseClicked(MouseEvent e) { - if (isHyperlinkEvent(e) && !e.isPopupTrigger() && e.getClickCount() == 1 && e.getButton() == MouseEvent.BUTTON1) { + cancelTooltip(); + + HyperlinkType type = getHyperlinkType(e); + + if (type != null && !e.isPopupTrigger() && e.getClickCount() == 1 && e.getButton() == MouseEvent.BUTTON1) { int position = component.viewToModel(e.getPoint()); if (position < 0) { return ; } - performAction(position); + performAction(position, type); } } Index: libsrc/org/netbeans/lib/editor/hyperlink/HyperlinkProviderManager.java =================================================================== RCS file: /cvs/editor/libsrc/org/netbeans/lib/editor/hyperlink/HyperlinkProviderManager.java,v retrieving revision 1.3 diff -u -r1.3 HyperlinkProviderManager.java --- libsrc/org/netbeans/lib/editor/hyperlink/HyperlinkProviderManager.java 15 Apr 2007 23:08:52 -0000 1.3 +++ libsrc/org/netbeans/lib/editor/hyperlink/HyperlinkProviderManager.java 11 Sep 2007 14:23:45 -0000 @@ -23,6 +23,7 @@ import org.netbeans.api.editor.mimelookup.MimeLookup; import org.netbeans.api.editor.mimelookup.MimePath; import org.netbeans.lib.editor.hyperlink.spi.HyperlinkProvider; +import org.netbeans.lib.editor.hyperlink.spi.HyperlinkProviderExt; import org.netbeans.spi.editor.mimelookup.Class2LayerFolder; import org.netbeans.spi.editor.mimelookup.InstanceProvider; Index: libsrc/org/netbeans/lib/editor/hyperlink/HyperlinkProviderManagerExt.java =================================================================== RCS file: libsrc/org/netbeans/lib/editor/hyperlink/HyperlinkProviderManagerExt.java diff -N libsrc/org/netbeans/lib/editor/hyperlink/HyperlinkProviderManagerExt.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ libsrc/org/netbeans/lib/editor/hyperlink/HyperlinkProviderManagerExt.java 11 Sep 2007 14:23:45 -0000 @@ -0,0 +1,63 @@ +/* + * The contents of this file are subject to the terms of the Common Development + * and Distribution License (the License). You may not use this file except in + * compliance with the License. + * + * You can obtain a copy of the License at http://www.netbeans.org/cddl.html + * or http://www.netbeans.org/cddl.txt. + * + * When distributing Covered Code, include this CDDL Header Notice in each file + * and include the License file at http://www.netbeans.org/cddl.txt. + * If applicable, add the following below the CDDL Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.lib.editor.hyperlink; + +import java.util.Collection; +import org.netbeans.api.editor.mimelookup.MimeLookup; +import org.netbeans.api.editor.mimelookup.MimePath; +import org.netbeans.lib.editor.hyperlink.spi.HyperlinkProviderExt; +import org.netbeans.spi.editor.mimelookup.Class2LayerFolder; +import org.netbeans.spi.editor.mimelookup.InstanceProvider; + +/** + * This class provides a list of HyperlinkProviderExt(s) for a given mime type. + * + * @author Jan Lahoda + */ +public final class HyperlinkProviderManagerExt implements Class2LayerFolder { + + /** + * Gets the list of HyperlinkProviders for a given mime type. + * + * @param mimeType mime type to get the HyperlinkProviders for + * + * @return The list of HyperlinkProviders available for the given mime type. + */ + public static Collection getHyperlinkProviderExts(String mimeType) { + MimePath mimePath = MimePath.parse(mimeType); + return MimeLookup.getLookup(mimePath).lookupAll(HyperlinkProviderExt.class); + } + + public HyperlinkProviderManagerExt() { + + } + + public Class getClazz() { + return HyperlinkProviderExt.class; + } + + public String getLayerFolderName() { + return "HyperlinkProviders"; // NOI18N + } + + public InstanceProvider getInstanceProvider() { + return null; + } +} Index: libsrc/org/netbeans/lib/editor/hyperlink/spi/HyperlinkProviderExt.java =================================================================== RCS file: libsrc/org/netbeans/lib/editor/hyperlink/spi/HyperlinkProviderExt.java diff -N libsrc/org/netbeans/lib/editor/hyperlink/spi/HyperlinkProviderExt.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ libsrc/org/netbeans/lib/editor/hyperlink/spi/HyperlinkProviderExt.java 11 Sep 2007 14:23:45 -0000 @@ -0,0 +1,127 @@ +/* + * The contents of this file are subject to the terms of the Common Development + * and Distribution License (the License). You may not use this file except in + * compliance with the License. + * + * You can obtain a copy of the License at http://www.netbeans.org/cddl.html + * or http://www.netbeans.org/cddl.txt. + * + * When distributing Covered Code, include this CDDL Header Notice in each file + * and include the License file at http://www.netbeans.org/cddl.txt. + * If applicable, add the following below the CDDL Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.lib.editor.hyperlink.spi; + +import java.util.Set; +import javax.swing.text.Document; + +/** + * This interface should be implemented by anyone who whats to provide hyperlinking + * functionality in the source code. + *
+ * Its methods are called for all the opened editors of the given mime-type + * where the hyperlinking functionality gets requested. + * + *

+ * The providers need to be registered. + * For NetBeans IDE, the default approach is to use System FileSystem. + *
+ * The HyperlinkProvider(s) should be registered as ".instance" objects under + * Editors/<mime-type>/HyperlinkProviders directory. + *

+ * + *

+ * Please see {@link org.netbeans.lib.editor.hyperlink.HyperlinkProviderManager} + * for more details. + *

+ * + *

+ * Note: there is no assurance on the order of calling of the methods in this class. + * The callers may call the methods in any order and even do not call some of these methods + * at all. + *

+ * + * @author Jan Lahoda + * @since 1.18 + */ +public interface HyperlinkProviderExt { + + /**Returns all hyperlink types that are supported by this HyperlinkProvider. + * the resulting value should be constant over time. + * + * @return supported hyperlink types + * @since 1.18 + */ + Set getSupportedHyperlinkTypes(); + + /** + * Should determine whether there should be a hyperlink on the given offset + * in the given document. May be called any number of times for given parameters. + *
+ * This method is called from event dispatch thread. + * It should run very fast as it is called very often. + * + * @param doc document on which to operate. + * @param offset >=0 offset to test (it generally should be offset < doc.getLength(), but + * the implementations should not depend on it) + * @param type the hyperlink type + * @return true if the provided offset should be in a hyperlink + * false otherwise + * @since 1.18 + */ + boolean isHyperlinkPoint(Document doc, int offset, HyperlinkType type); + + /** + * Should determine the span of hyperlink on given offset. Generally, if + * isHyperlinkPoint returns true for a given parameters, this class should + * return a valid span, but it is not strictly required. + *
+ * This method is called from event dispatch thread. + * This method should run very fast as it is called very often. + * + * @param doc document on which to operate. + * @param offset >=0 offset to test (it generally should be offset < doc.getLength(), but + * the implementations should not depend on it) + * @param type the hyperlink type + * @return a two member array which contains starting and ending offset of a hyperlink + * that should be on a given offset + * @since 1.18 + */ + int[] getHyperlinkSpan(Document doc, int offset, HyperlinkType type); + + /** + * The implementor should perform an action + * corresponding to clicking on the hyperlink on the given offset. The + * nature of the action is given by the nature of given hyperlink, but + * generally should open some resource or move cursor + * to certain place in the current document. + * + * @param doc document on which to operate. + * @param offset >=0 offset to test (it generally should be offset < doc.getLength(), but + * the implementations should not depend on it) + * @param type the hyperlink type + * @since 1.18 + */ + void performClickAction(Document doc, int offset, HyperlinkType type); + + /** Get a short description/tooltip corresponding to the given offset. + * Should block until the result is computed. Is called in a working thread, + * not in AWT Event dispatch thread. Return null if there should + * be no tooltip. + * + * @param doc document on which to operate. + * @param offset >=0 offset to test (it generally should be offset < doc.getLength(), but + * the implementations should not depend on it) + * @param type the hyperlink type + * @since 1.18 + */ + String getTooltipText(Document doc, int offset, HyperlinkType type); + +} Index: libsrc/org/netbeans/lib/editor/hyperlink/spi/HyperlinkType.java =================================================================== RCS file: libsrc/org/netbeans/lib/editor/hyperlink/spi/HyperlinkType.java diff -N libsrc/org/netbeans/lib/editor/hyperlink/spi/HyperlinkType.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ libsrc/org/netbeans/lib/editor/hyperlink/spi/HyperlinkType.java 11 Sep 2007 14:23:45 -0000 @@ -0,0 +1,34 @@ +/* + * The contents of this file are subject to the terms of the Common Development + * and Distribution License (the License). You may not use this file except in + * compliance with the License. + * + * You can obtain a copy of the License at http://www.netbeans.org/cddl.html + * or http://www.netbeans.org/cddl.txt. + * + * When distributing Covered Code, include this CDDL Header Notice in each file + * and include the License file at http://www.netbeans.org/cddl.txt. + * If applicable, add the following below the CDDL Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun + * Microsystems, Inc. All Rights Reserved. + */ +package org.netbeans.lib.editor.hyperlink.spi; + +/**A type of work for hyperlinks. Currently, there is only one hyperlink type + * (go to declaration), but more can be introduced in the future. + * + * @since 1.18 + * @author Jan Lahoda + */ +public enum HyperlinkType { + + /** + * @since 1.18 + */ + GO_TO_DECLARATION, + +}