/** * <copyright> * * Copyright (c) 2008,2010 Eclipse Modeling Project 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: * E.D.Willink - initial API and implementation * * </copyright> * * $Id: CommonHoverHelper.java,v 1.1 2010/03/11 14:51:20 ewillink Exp $ */ package org.eclipse.ocl.examples.editor.ui.imp; import java.util.List; import org.eclipse.imp.editor.AnnotationHoverBase; import org.eclipse.imp.language.ServiceFactory; import org.eclipse.imp.parser.IParseController; import org.eclipse.imp.parser.ISourcePositionLocator; import org.eclipse.imp.services.IDocumentationProvider; import org.eclipse.imp.services.IHoverHelper; import org.eclipse.imp.services.IReferenceResolver; import org.eclipse.imp.services.base.HoverHelperBase; import org.eclipse.imp.utils.HTMLPrinter; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.source.Annotation; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.ocl.cst.CSTNode; import org.eclipse.ocl.examples.common.utils.TracingOption; import org.eclipse.ocl.examples.editor.ui.OCLExamplesEditorPlugin; public abstract class CommonHoverHelper extends HoverHelperBase implements IHoverHelper { public static TracingOption hoverDebug = new TracingOption(OCLExamplesEditorPlugin.PLUGIN_ID, "hover/debug"); IReferenceResolver fResolver = null; public String getHoverHelpAt(IParseController parseController, ISourceViewer srcViewer, int offset) { CommonParseController commonParseController = (CommonParseController) parseController; // If there are any annotations associated with the line that contains // the given offset, return those try { // @SuppressWarnings("unchecked") List<Annotation> annotations = AnnotationHoverBase.getSourceAnnotationsForLine( srcViewer, srcViewer.getDocument().getLineOfOffset(offset)); if (annotations != null && annotations.size() > 0) { // Some annotations have no text, such as breakpoint annotations; // if that's all we have, then don't bother returning it String msg = AnnotationHoverBase.formatAnnotationList(annotations); if (msg != null) { return msg; } } } catch (BadLocationException e) { return "??? (BadLocationException for annotation)"; } // Otherwise, return a message determined directly or indirectly based // on the node whose representation occurs at the given offset // Get the current AST; no AST implies no message ICommonParseResult parseResult = commonParseController.getCurrentResult(); if (parseResult == null) return null; CSTNode cst = parseResult.getCST(); if (cst == null) return null; // Declare variables used in formulating the message Object sourceNode = null; // node at current hover point Object targetNode = null; // node referenced from current hover point Object helpNode = null; // node for which a help message is to be constructed String msg = null; // the help message for helpNode // Get the node at the given offset; no node implies no message ISourcePositionLocator nodeLocator = parseResult.getSourcePositionLocator(); sourceNode = nodeLocator.findNode(cst, offset); if (sourceNode == null) return null; // Check whether there is a reference resolver for the identified // source node; if so, attempt to get the node that is referenced by // the source node, on the assumption that the referenced node should // be the basis for the help message (e.g., as a decl for an identifier) if (true) { if (fResolver == null && fLanguage != null) { try { fResolver = ServiceFactory.getInstance().getReferenceResolver(fLanguage); } catch (Exception e) { getPlugin().writeErrorMsg("Exception getting Reference Resolver service from service factory"); fResolver = null; } } if (fResolver != null) { targetNode = fResolver.getLinkTarget(sourceNode, commonParseController); // FIXME need to pass offset if PathNameCS is to be fragmented } } if (hoverDebug.isActive()) hoverDebug.println("Hover at " + offset + " on" + " source: " + sourceNode.getClass().getSimpleName() + " target: " + (targetNode != null ? targetNode.getClass().getSimpleName() : "null")); // If the target node is not null, provide help based on that; // otherwise, provide help based on the source node if (targetNode != null) helpNode = targetNode; else helpNode = sourceNode; // Now need to determine whether the help message should be determined // based on the text represented by the node or based on some separate // text provided through an IDocumentationProvider // Check whether there is a documentation provider for the language; // if so, check whether it provides documentation for the help node; // if so, return that documentation IDocumentationProvider docProvider = null; if (fLanguage != null && true) { try { docProvider = ServiceFactory.getInstance().getDocumentationProvider(fLanguage); } catch (Exception e) { getPlugin().writeErrorMsg("Exception getting Documentation Provider Service from service factory"); fResolver = null; } } if (docProvider != null) { msg = docProvider.getDocumentation(helpNode, commonParseController); if (msg != null) return HTMLPrinter.convertToHTMLContent(msg); } // Otherwise, base the help message on the text that is represented // by the help node if (helpNode instanceof CSTNode) { CSTNode def = (CSTNode) helpNode; msg = parseResult.getTextRange(def.getStartOffset(), def.getEndOffset() - def.getStartOffset() + 1); int maxMsgLen = 80; if (msg == null || msg.length() == 0) return "No help available"; else if (msg.length() <= maxMsgLen) return msg; else return msg.subSequence(0, maxMsgLen) + "..."; } else { return "No help available"; } } protected abstract ICommonPlugin getPlugin(); }