/******************************************************************************* * Copyright (c) 2000, 2017 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 * *******************************************************************************/ package org.eclipse.dltk.internal.ui.text.hover; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.StringTokenizer; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.dltk.internal.ui.editor.EditorUtility; import org.eclipse.dltk.ui.DLTKUIPlugin; import org.eclipse.dltk.ui.PreferenceConstants; import org.eclipse.dltk.ui.text.hover.IScriptEditorTextHover; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.swt.SWT; import org.osgi.framework.Bundle; /** * Describes a editor text hover. */ public class EditorTextHoverDescriptor { private static final String EDITOR_TEXT_HOVER_EXTENSION_POINT = "org.eclipse.dltk.ui.editorTextHovers"; //$NON-NLS-1$ private static final String HOVER_TAG = "hover"; //$NON-NLS-1$ private static final String ID_ATTRIBUTE = "id"; //$NON-NLS-1$ private static final String CLASS_ATTRIBUTE = "class"; //$NON-NLS-1$ private static final String LABEL_ATTRIBUTE = "label"; //$NON-NLS-1$ private static final String ACTIVATE_PLUG_IN_ATTRIBUTE = "activate"; //$NON-NLS-1$ private static final String DESCRIPTION_ATTRIBUTE = "description"; //$NON-NLS-1$ private static final String NATURE_ATTRIBUTE = "nature"; //$NON-NLS-1$ public static final String NO_MODIFIER = "0"; //$NON-NLS-1$ public static final String DISABLED_TAG = "!"; //$NON-NLS-1$ public static final String VALUE_SEPARATOR = ";"; //$NON-NLS-1$ private int fStateMask; private String fModifierString; private boolean fIsEnabled; private IConfigurationElement fElement; /** * Returns all editor text hovers contributed to the workbench. * * @deprecated */ @Deprecated public static EditorTextHoverDescriptor[] getContributedHovers( IPreferenceStore store) { return getContributedHovers(null, store); } /** * Returns all editor text hovers contributed to the workbench for the * specified nature. */ public static EditorTextHoverDescriptor[] getContributedHovers( String natureId, IPreferenceStore store) { IExtensionRegistry registry = Platform.getExtensionRegistry(); IConfigurationElement[] elements = registry .getConfigurationElementsFor(EDITOR_TEXT_HOVER_EXTENSION_POINT); EditorTextHoverDescriptor[] hoverDescs = createDescriptors(elements, natureId); initializeFromPreferences(hoverDescs, store); return hoverDescs; } /** * Computes the state mask for the given modifier string. * * @param modifiers * the string with the modifiers, separated by '+', '-', ';', ',' * or '.' * @return the state mask or -1 if the input is invalid */ public static int computeStateMask(String modifiers) { if (modifiers == null) return -1; if (modifiers.length() == 0) return SWT.NONE; int stateMask = 0; StringTokenizer modifierTokenizer = new StringTokenizer(modifiers, ",;.:+-* "); //$NON-NLS-1$ while (modifierTokenizer.hasMoreTokens()) { int modifier = EditorUtility .findLocalizedModifier(modifierTokenizer.nextToken()); if (modifier == 0 || (stateMask & modifier) == modifier) return -1; stateMask = stateMask | modifier; } return stateMask; } /** * Creates a new Script Editor text hover descriptor from the given * configuration element. */ private EditorTextHoverDescriptor(IConfigurationElement element) { fElement = element; } /** * Creates the editor text hover. */ public IScriptEditorTextHover createTextHover() { String pluginId = fElement.getContributor().getName(); boolean isHoversPlugInActivated = Platform.getBundle(pluginId) .getState() == Bundle.ACTIVE; if (isHoversPlugInActivated || canActivatePlugIn()) { try { return (IScriptEditorTextHover) fElement .createExecutableExtension(CLASS_ATTRIBUTE); } catch (CoreException x) { DLTKUIPlugin.log(new Status(IStatus.ERROR, DLTKUIPlugin.getPluginId(), 0, "DLTKHoverMessages.JavaTextHover_createTextHover", //$NON-NLS-1$ null)); } } return null; } // ---- XML Attribute accessors // --------------------------------------------- /** * Returns the hover's id. */ public String getId() { return fElement.getAttribute(ID_ATTRIBUTE); } /** * Returns the hover's class name. */ public String getHoverClassName() { return fElement.getAttribute(CLASS_ATTRIBUTE); } /** * Returns the hover's label. */ public String getLabel() { String label = fElement.getAttribute(LABEL_ATTRIBUTE); if (label != null) return label; // Return simple class name label = getHoverClassName(); int lastDot = label.lastIndexOf('.'); if (lastDot >= 0 && lastDot < label.length() - 1) return label.substring(lastDot + 1); else return label; } /** * Returns the hover's description. * * @return the hover's description or <code>null</code> if not provided */ public String getDescription() { return fElement.getAttribute(DESCRIPTION_ATTRIBUTE); } public String getNature() { return fElement.getAttribute(NATURE_ATTRIBUTE); } public boolean canActivatePlugIn() { return Boolean .valueOf(fElement.getAttribute(ACTIVATE_PLUG_IN_ATTRIBUTE)) .booleanValue(); } @Override public boolean equals(Object obj) { if (obj == null || !obj.getClass().equals(this.getClass()) || getId() == null) return false; return getId().equals(((EditorTextHoverDescriptor) obj).getId()); } @Override public int hashCode() { return getId().hashCode(); } private static EditorTextHoverDescriptor[] createDescriptors( IConfigurationElement[] elements, String natureId) { List<EditorTextHoverDescriptor> result = new ArrayList<>( elements.length); for (int i = 0; i < elements.length; i++) { IConfigurationElement element = elements[i]; if (HOVER_TAG.equals(element.getName())) { final String elementNature = element .getAttribute(NATURE_ATTRIBUTE); if (elementNature == null || elementNature.equals(natureId)) { EditorTextHoverDescriptor desc = new EditorTextHoverDescriptor( element); result.add(desc); } } } return result.toArray(new EditorTextHoverDescriptor[result.size()]); } private static void initializeFromPreferences( EditorTextHoverDescriptor[] hovers, IPreferenceStore store) { String compiledTextHoverModifiers = store .getString(PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS); StringTokenizer tokenizer = new StringTokenizer( compiledTextHoverModifiers, VALUE_SEPARATOR); HashMap<String, String> idToModifier = new HashMap<>( tokenizer.countTokens() / 2); while (tokenizer.hasMoreTokens()) { String id = tokenizer.nextToken(); if (tokenizer.hasMoreTokens()) idToModifier.put(id, tokenizer.nextToken()); } String compiledTextHoverModifierMasks = store.getString( PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIER_MASKS); tokenizer = new StringTokenizer(compiledTextHoverModifierMasks, VALUE_SEPARATOR); HashMap<String, String> idToModifierMask = new HashMap<>( tokenizer.countTokens() / 2); while (tokenizer.hasMoreTokens()) { String id = tokenizer.nextToken(); if (tokenizer.hasMoreTokens()) idToModifierMask.put(id, tokenizer.nextToken()); } for (int i = 0; i < hovers.length; i++) { String modifierString = idToModifier.get(hovers[i].getId()); boolean enabled = true; if (modifierString == null) modifierString = DISABLED_TAG; if (modifierString.startsWith(DISABLED_TAG)) { enabled = false; modifierString = modifierString.substring(1); } if (modifierString.equals(NO_MODIFIER)) modifierString = ""; //$NON-NLS-1$ hovers[i].fModifierString = modifierString; hovers[i].fIsEnabled = enabled; hovers[i].fStateMask = computeStateMask(modifierString); if (hovers[i].fStateMask == -1) { // Fallback: use stored modifier masks try { hovers[i].fStateMask = Integer .parseInt(idToModifierMask.get(hovers[i].getId())); } catch (NumberFormatException ex) { hovers[i].fStateMask = -1; } // Fix modifier string int stateMask = hovers[i].fStateMask; if (stateMask == -1) hovers[i].fModifierString = ""; //$NON-NLS-1$ else hovers[i].fModifierString = EditorUtility .getModifierString(stateMask); } } } /** * Returns the configured modifier getStateMask for this hover. * * @return the hover modifier stateMask or -1 if no hover is configured */ public int getStateMask() { return fStateMask; } /** * Returns the modifier String as set in the preference store. * * @return the modifier string */ public String getModifierString() { return fModifierString; } /** * Returns whether this hover is enabled or not. * * @return <code>true</code> if enabled */ public boolean isEnabled() { return fIsEnabled; } /** * Returns this hover descriptors configuration element. * * @return the configuration element * */ public IConfigurationElement getConfigurationElement() { return fElement; } }