/** * Aptana Studio * Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the GNU Public License (GPL) v3 (with exceptions). * Please see the license.html included with this distribution for details. * Any modifications to this file must keep this entire header intact. */ package com.aptana.ruby.internal.debug.ui; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IVariable; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.debug.ui.IDebugModelPresentation; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextHover; import org.eclipse.jface.text.ITextHoverExtension2; import org.eclipse.jface.text.ITextViewer; import com.aptana.ruby.debug.core.RubyDebugModel; import com.aptana.ruby.debug.core.model.IRubyStackFrame; /** * @author Max Stepanov * @author cwilliams */ public class RubyDebugHover implements ITextHover, ITextHoverExtension2 { private static IDebugModelPresentation modelPresentation; /* * (non-Javadoc) * @see org.eclipse.jface.text.ITextHover#getHoverInfo(org.eclipse.jface.text.ITextViewer, * org.eclipse.jface.text.IRegion) */ public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) { Object info = getHoverInfo2(textViewer, hoverRegion); return info != null ? info.toString() : null; } /* * (non-Javadoc) * @see org.eclipse.jface.text.ITextHover#getHoverRegion(org.eclipse.jface.text.ITextViewer, int) */ public IRegion getHoverRegion(ITextViewer textViewer, int offset) { return null; // JavaWordFinder.findWord(textViewer.getDocument(), offset); } /* * (non-Javadoc) * @see org.eclipse.jface.text.ITextHoverExtension2#getHoverInfo2(org.eclipse.jface.text.ITextViewer, * org.eclipse.jface.text.IRegion) */ public Object getHoverInfo2(ITextViewer textViewer, IRegion hoverRegion) { IRubyStackFrame frame = getFrame(); if (frame != null) { IDocument document = textViewer.getDocument(); if (document != null) { try { String variableName = document.get(hoverRegion.getOffset(), hoverRegion.getLength()); try { IVariable[] variables = frame.getVariables(); if (variables != null) { for (IVariable variable : variables) { if (variableName.equals(variable.getName())) { return getVariableText(variable); } } } } catch (DebugException e) { return null; } } catch (BadLocationException e) { return null; } } } return null; } private IRubyStackFrame getFrame() { IAdaptable adaptable = DebugUITools.getDebugContext(); if (adaptable != null) { return (IRubyStackFrame) adaptable.getAdapter(IRubyStackFrame.class); } return null; } /* * Returns HTML text for the given variable */ private String getVariableText(IVariable variable) { StringBuilder sb = new StringBuilder(); IDebugModelPresentation modelPresentation = getModelPresentation(); sb.append("<p><pre>"); //$NON-NLS-1$ String variableText = modelPresentation.getText(variable); sb.append(replaceHTMLChars(variableText)); sb.append("</pre></p>"); //$NON-NLS-1$ if (sb.length() > 0) { return sb.toString(); } return null; } /* * Replaces reserved HTML characters in the given string with their escaped equivalents. This is to ensure that * variable values containing reserved characters are correctly displayed. */ private static String replaceHTMLChars(String variableText) { StringBuilder sb = new StringBuilder(variableText.length()); char[] characters = variableText.toCharArray(); for (int i = 0; i < characters.length; i++) { char character = characters[i]; switch (character) { case '<': sb.append("<"); //$NON-NLS-1$ break; case '>': sb.append(">"); //$NON-NLS-1$ break; case '&': sb.append("&"); //$NON-NLS-1$ break; case '"': sb.append("""); //$NON-NLS-1$ break; default: sb.append(character); } } return sb.toString(); } private static IDebugModelPresentation getModelPresentation() { if (modelPresentation == null) { modelPresentation = DebugUITools.newDebugModelPresentation(RubyDebugModel.getModelIdentifier()); modelPresentation.setAttribute(IDebugModelPresentation.DISPLAY_VARIABLE_TYPE_NAMES, Boolean.TRUE); } return modelPresentation; } }