mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-25 09:55:29 +02:00
Bug 200418 - Mouse over struct/class member always fails
This commit is contained in:
parent
f3955789de
commit
450bef3a2c
2 changed files with 318 additions and 280 deletions
|
@ -1,5 +1,5 @@
|
|||
###############################################################################
|
||||
# Copyright (c) 2003, 2007 QNX Software Systems and others.
|
||||
# Copyright (c) 2003, 2009 QNX Software Systems 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
|
||||
|
@ -9,6 +9,7 @@
|
|||
# QNX Software Systems - initial API and implementation
|
||||
###############################################################################
|
||||
|
||||
AbstractDebugTextHover.jobName=Computing hover expression
|
||||
CDebugModelPresentation.unknown_1=unknown
|
||||
CDebugImageDescriptorRegistry.0=Allocating image for wrong display.
|
||||
CDebugModelPresentation.not_available_1=<not available>
|
||||
|
|
|
@ -1,279 +1,316 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2000, 2007 QNX Software Systems 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:
|
||||
* QNX Software Systems - Initial API and implementation
|
||||
* Nokia - Refactored from DebugTextHover to remove CDI dependency
|
||||
*
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.debug.ui.editors;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.cdt.debug.internal.ui.CDebugUIUtils;
|
||||
import org.eclipse.cdt.debug.ui.CDebugUIPlugin;
|
||||
import org.eclipse.cdt.ui.text.c.hover.ICEditorTextHover;
|
||||
import org.eclipse.core.runtime.IAdaptable;
|
||||
import org.eclipse.debug.core.DebugException;
|
||||
import org.eclipse.debug.ui.IDebugUIConstants;
|
||||
import org.eclipse.jface.text.BadLocationException;
|
||||
import org.eclipse.jface.text.IDocument;
|
||||
import org.eclipse.jface.text.IInformationControlCreator;
|
||||
import org.eclipse.jface.text.IRegion;
|
||||
import org.eclipse.jface.text.ITextHoverExtension;
|
||||
import org.eclipse.jface.text.ITextViewer;
|
||||
import org.eclipse.jface.viewers.ISelection;
|
||||
import org.eclipse.jface.viewers.IStructuredSelection;
|
||||
import org.eclipse.ui.IEditorPart;
|
||||
import org.eclipse.ui.IPartListener;
|
||||
import org.eclipse.ui.ISelectionListener;
|
||||
import org.eclipse.ui.IWorkbenchPage;
|
||||
import org.eclipse.ui.IWorkbenchPart;
|
||||
|
||||
/* The class LanguageOperators protects some language specific
|
||||
* operator information used by the DebugTextHover class.
|
||||
*/
|
||||
|
||||
class LanguageOperators {
|
||||
public String getAssignmentOperator() {
|
||||
return "="; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public String getGreaterThanEqualToOperator() {
|
||||
return ">="; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public String getEqualToOperator() {
|
||||
return "=="; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public String getNotEqualToOperator() {
|
||||
return "!="; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public String getLessThenEqualToOperator() {
|
||||
return "<="; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public String getValueChangeOperatorsRegex() {
|
||||
return "(\\+\\+)|(\\-\\-)|(\\+\\=)|" //$NON-NLS-1$
|
||||
+ "(\\-\\=)|(\\*\\=)|(/\\=)|(\\&\\=)" //$NON-NLS-1$
|
||||
+ "(\\%\\=)|(\\^\\=)|(\\|\\=)|(\\<\\<\\=)|(\\>\\>\\=)"; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public String getEqualToOperatorsRegex() {
|
||||
return "\\=\\=|\\<\\=|\\>\\=|!\\="; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public String getIdentifierRegex() {
|
||||
return "[_A-Za-z][_A-Za-z0-9]*"; //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The text hovering support for C/C++ debugger.
|
||||
*
|
||||
* @since 6.1
|
||||
*/
|
||||
|
||||
public abstract class AbstractDebugTextHover implements ICEditorTextHover, ITextHoverExtension,
|
||||
ISelectionListener, IPartListener {
|
||||
|
||||
static final private int MAX_HOVER_INFO_SIZE = 100;
|
||||
|
||||
private ISelection fSelection = null;
|
||||
|
||||
private IEditorPart fEditor;
|
||||
|
||||
protected abstract boolean canEvaluate();
|
||||
|
||||
protected abstract String evaluateExpression(String expression);
|
||||
|
||||
public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
|
||||
if (canEvaluate()) {
|
||||
try {
|
||||
IDocument document = textViewer.getDocument();
|
||||
if (document == null)
|
||||
return null;
|
||||
String expression = document.get(hoverRegion.getOffset(),
|
||||
hoverRegion.getLength());
|
||||
if (expression == null)
|
||||
return null;
|
||||
expression = expression.trim();
|
||||
if (expression.length() == 0)
|
||||
return null;
|
||||
LanguageOperators operatorsObj = new LanguageOperators();
|
||||
|
||||
Pattern pattern = Pattern.compile(operatorsObj
|
||||
.getValueChangeOperatorsRegex());
|
||||
Matcher matcher = pattern.matcher(expression);
|
||||
|
||||
boolean match_found = matcher.find();
|
||||
// Get matching string
|
||||
// If the expression has some operators which can change the
|
||||
// value of a variable, that expresssion should not be
|
||||
// evaluated.
|
||||
if (match_found) {
|
||||
return null;
|
||||
}
|
||||
pattern = Pattern.compile(operatorsObj
|
||||
.getEqualToOperatorsRegex());
|
||||
String[] tokens = pattern.split(expression);
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
//If the expression contains assignment operator that
|
||||
// can change the value of a variable, the expression
|
||||
// should not be evaluated.
|
||||
if (tokens[i].indexOf(operatorsObj
|
||||
.getAssignmentOperator()) != -1)
|
||||
return null;
|
||||
}
|
||||
//Supressing function calls from evaluation.
|
||||
String functionCallRegex = operatorsObj.getIdentifierRegex() + "\\s*\\("; //$NON-NLS-1$
|
||||
pattern = Pattern.compile(functionCallRegex);
|
||||
matcher = pattern.matcher(expression);
|
||||
match_found = matcher.find();
|
||||
if (match_found) {
|
||||
return null;
|
||||
}
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
String result = evaluateExpression(expression);
|
||||
if (result == null)
|
||||
return null;
|
||||
try {
|
||||
appendVariable(buffer, makeHTMLSafe(expression), makeHTMLSafe(result.trim()));
|
||||
} catch (DebugException x) {
|
||||
CDebugUIPlugin.log(x);
|
||||
}
|
||||
if (buffer.length() > 0) {
|
||||
return buffer.toString();
|
||||
}
|
||||
} catch (BadLocationException x) {
|
||||
CDebugUIPlugin.log(x);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public IRegion getHoverRegion(ITextViewer viewer, int offset) {
|
||||
/*
|
||||
* Point selectedRange = viewer.getSelectedRange(); if ( selectedRange.x >= 0 && selectedRange.y > 0 && offset >= selectedRange.x && offset <=
|
||||
* selectedRange.x + selectedRange.y ) return new Region( selectedRange.x, selectedRange.y );
|
||||
*/
|
||||
if (viewer != null)
|
||||
return CDebugUIUtils.findWord(viewer.getDocument(), offset);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append HTML for the given variable to the given buffer
|
||||
*/
|
||||
private static void appendVariable(StringBuffer buffer, String expression, String value) throws DebugException {
|
||||
if (value.length() > MAX_HOVER_INFO_SIZE)
|
||||
value = value.substring(0, MAX_HOVER_INFO_SIZE) + " ..."; //$NON-NLS-1$
|
||||
buffer.append("<p>"); //$NON-NLS-1$
|
||||
buffer.append("<pre>").append(expression).append("</pre>"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
buffer.append(" = "); //$NON-NLS-1$
|
||||
buffer.append("<b><pre>").append(value).append("</pre></b>"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
buffer.append("</p>"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public void setEditor(IEditorPart editor) {
|
||||
if (editor != null) {
|
||||
fEditor = editor;
|
||||
final IWorkbenchPage page = editor.getSite().getPage();
|
||||
page.addSelectionListener(IDebugUIConstants.ID_DEBUG_VIEW, this);
|
||||
page.addPartListener(this);
|
||||
// initialize selection
|
||||
Runnable r = new Runnable() {
|
||||
|
||||
public void run() {
|
||||
fSelection = page
|
||||
.getSelection(IDebugUIConstants.ID_DEBUG_VIEW);
|
||||
}
|
||||
};
|
||||
CDebugUIPlugin.getStandardDisplay().asyncExec(r);
|
||||
}
|
||||
}
|
||||
|
||||
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
|
||||
fSelection = selection;
|
||||
}
|
||||
|
||||
public void partActivated(IWorkbenchPart part) {
|
||||
}
|
||||
|
||||
public void partBroughtToTop(IWorkbenchPart part) {
|
||||
}
|
||||
|
||||
public void partClosed(IWorkbenchPart part) {
|
||||
if (part.equals(fEditor)) {
|
||||
IWorkbenchPage page = fEditor.getSite().getPage();
|
||||
page.removeSelectionListener(IDebugUIConstants.ID_DEBUG_VIEW, this);
|
||||
page.removePartListener(this);
|
||||
fSelection = null;
|
||||
fEditor = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void partDeactivated(IWorkbenchPart part) {
|
||||
}
|
||||
|
||||
public void partOpened(IWorkbenchPart part) {
|
||||
}
|
||||
|
||||
public IInformationControlCreator getHoverControlCreator() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected ISelection getSelection() {
|
||||
return fSelection;
|
||||
}
|
||||
|
||||
protected IAdaptable getSelectionAdaptable() {
|
||||
if (fSelection instanceof IStructuredSelection) {
|
||||
IStructuredSelection selection = (IStructuredSelection) fSelection;
|
||||
if (selection.size() == 1) {
|
||||
Object element = selection.getFirstElement();
|
||||
if (element instanceof IAdaptable) {
|
||||
return (IAdaptable) element;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected IEditorPart getEditor() {
|
||||
return fEditor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace any characters in the given String that would confuse an HTML parser with their escape sequences.
|
||||
*/
|
||||
private static String makeHTMLSafe(String string) {
|
||||
StringBuffer buffer = new StringBuffer(string.length());
|
||||
for (int i = 0; i != string.length(); i++) {
|
||||
char ch = string.charAt(i);
|
||||
switch (ch) {
|
||||
case '&':
|
||||
buffer.append("&"); //$NON-NLS-1$
|
||||
break;
|
||||
case '<':
|
||||
buffer.append("<"); //$NON-NLS-1$
|
||||
break;
|
||||
case '>':
|
||||
buffer.append(">"); //$NON-NLS-1$
|
||||
break;
|
||||
default:
|
||||
buffer.append(ch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2000, 2009 QNX Software Systems 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:
|
||||
* QNX Software Systems - Initial API and implementation
|
||||
* Nokia - Refactored from DebugTextHover to remove CDI dependency
|
||||
* Wind River Systems - Bug 200418
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.debug.ui.editors;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression;
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
import org.eclipse.cdt.core.model.ILanguage;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
import org.eclipse.cdt.debug.internal.ui.CDebugUIMessages;
|
||||
import org.eclipse.cdt.debug.internal.ui.CDebugUIUtils;
|
||||
import org.eclipse.cdt.debug.ui.CDebugUIPlugin;
|
||||
import org.eclipse.cdt.ui.CDTUITools;
|
||||
import org.eclipse.cdt.ui.text.ICPartitions;
|
||||
import org.eclipse.cdt.ui.text.SharedASTJob;
|
||||
import org.eclipse.cdt.ui.text.c.hover.ICEditorTextHover;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IAdaptable;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.eclipse.debug.core.DebugException;
|
||||
import org.eclipse.debug.ui.DebugUITools;
|
||||
import org.eclipse.jface.text.BadLocationException;
|
||||
import org.eclipse.jface.text.IDocument;
|
||||
import org.eclipse.jface.text.IInformationControlCreator;
|
||||
import org.eclipse.jface.text.IRegion;
|
||||
import org.eclipse.jface.text.ITextHoverExtension;
|
||||
import org.eclipse.jface.text.ITextViewer;
|
||||
import org.eclipse.jface.text.ITypedRegion;
|
||||
import org.eclipse.jface.text.Position;
|
||||
import org.eclipse.jface.text.TextUtilities;
|
||||
import org.eclipse.ui.IEditorPart;
|
||||
|
||||
/**
|
||||
* The text hovering support for C/C++ debugger.
|
||||
*
|
||||
* @since 6.1
|
||||
*/
|
||||
public abstract class AbstractDebugTextHover implements ICEditorTextHover, ITextHoverExtension {
|
||||
|
||||
/**
|
||||
* ASTVisitor checking for side-effect expressions.
|
||||
*/
|
||||
private static class ExpressionChecker extends ASTVisitor {
|
||||
private boolean fValid;
|
||||
private ExpressionChecker() {
|
||||
shouldVisitExpressions = true;
|
||||
}
|
||||
private boolean check(IASTNode node) {
|
||||
fValid = true;
|
||||
node.accept(this);
|
||||
return fValid;
|
||||
};
|
||||
@Override
|
||||
public int visit(IASTExpression expression) {
|
||||
if (expression instanceof IASTFunctionCallExpression) {
|
||||
fValid = false;
|
||||
} else if (expression instanceof IASTUnaryExpression) {
|
||||
IASTUnaryExpression unaryExpression = (IASTUnaryExpression) expression;
|
||||
switch (unaryExpression.getOperator()) {
|
||||
case IASTUnaryExpression.op_postFixDecr:
|
||||
case IASTUnaryExpression.op_postFixIncr:
|
||||
case IASTUnaryExpression.op_prefixIncr:
|
||||
case IASTUnaryExpression.op_prefixDecr:
|
||||
fValid = false;
|
||||
break;
|
||||
}
|
||||
} else if (expression instanceof IASTBinaryExpression) {
|
||||
IASTBinaryExpression binaryExpression = (IASTBinaryExpression) expression;
|
||||
switch (binaryExpression.getOperator()) {
|
||||
case IASTBinaryExpression.op_binaryAndAssign:
|
||||
case IASTBinaryExpression.op_binaryOrAssign:
|
||||
case IASTBinaryExpression.op_binaryXorAssign:
|
||||
case IASTBinaryExpression.op_divideAssign:
|
||||
case IASTBinaryExpression.op_minusAssign:
|
||||
case IASTBinaryExpression.op_moduloAssign:
|
||||
case IASTBinaryExpression.op_multiplyAssign:
|
||||
case IASTBinaryExpression.op_plusAssign:
|
||||
case IASTBinaryExpression.op_shiftLeftAssign:
|
||||
case IASTBinaryExpression.op_shiftRightAssign:
|
||||
fValid = false;
|
||||
break;
|
||||
}
|
||||
} else if (expression instanceof ICPPASTNewExpression) {
|
||||
fValid = false;
|
||||
} else if (expression instanceof ICPPASTDeleteExpression) {
|
||||
fValid = false;
|
||||
} else if (expression instanceof IGNUASTCompoundStatementExpression) {
|
||||
fValid = false;
|
||||
}
|
||||
if (!fValid)
|
||||
return PROCESS_ABORT;
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
}
|
||||
|
||||
static final private int MAX_HOVER_INFO_SIZE = 100;
|
||||
|
||||
private IEditorPart fEditor;
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if this hover can evaluate an expression
|
||||
*/
|
||||
protected abstract boolean canEvaluate();
|
||||
|
||||
/**
|
||||
* Compute a value for given expression.
|
||||
*
|
||||
* @param expression
|
||||
* @return a result string or <code>null</code> if the expression could not be evaluated
|
||||
*/
|
||||
protected abstract String evaluateExpression(String expression);
|
||||
|
||||
public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
|
||||
if (canEvaluate()) {
|
||||
String expression = getExpressionText(textViewer, hoverRegion);
|
||||
if (expression != null) {
|
||||
String result = evaluateExpression(expression);
|
||||
if (result == null)
|
||||
return null;
|
||||
try {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
appendVariable(buffer, makeHTMLSafe(expression), makeHTMLSafe(result.trim()));
|
||||
if (buffer.length() > 0) {
|
||||
return buffer.toString();
|
||||
}
|
||||
} catch (DebugException x) {
|
||||
CDebugUIPlugin.log(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public IRegion getHoverRegion(ITextViewer viewer, int offset) {
|
||||
/*
|
||||
* Point selectedRange = viewer.getSelectedRange(); if ( selectedRange.x >= 0 && selectedRange.y > 0 && offset >= selectedRange.x && offset <=
|
||||
* selectedRange.x + selectedRange.y ) return new Region( selectedRange.x, selectedRange.y );
|
||||
*/
|
||||
if (viewer != null)
|
||||
return CDebugUIUtils.findWord(viewer.getDocument(), offset);
|
||||
return null;
|
||||
}
|
||||
|
||||
public final void setEditor(IEditorPart editor) {
|
||||
if (editor != null) {
|
||||
fEditor = editor;
|
||||
}
|
||||
}
|
||||
|
||||
public IInformationControlCreator getHoverControlCreator() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compute the expression text to be evaluated by the debugger.
|
||||
* <p>
|
||||
* The default implementation uses an AST to compute a valid, side-effect free
|
||||
* expression.
|
||||
* </p>
|
||||
*
|
||||
* @param textViewer the underlying text viewer
|
||||
* @param hoverRegion the hover region as returned by {@link #getHoverRegion(ITextViewer, int)}
|
||||
* @return an expression string or <code>null</code> if no valid expression could be computed
|
||||
*/
|
||||
protected String getExpressionText(ITextViewer textViewer, final IRegion hoverRegion) {
|
||||
IDocument document = textViewer.getDocument();
|
||||
if (document == null)
|
||||
return null;
|
||||
ICElement cElement = CDTUITools.getEditorInputCElement(getEditor().getEditorInput());
|
||||
if (cElement instanceof ITranslationUnit) {
|
||||
final Position expressionPosition = new Position(0);
|
||||
SharedASTJob job = new SharedASTJob(CDebugUIMessages.getString("AbstractDebugTextHover.jobName"), (ITranslationUnit) cElement) { //$NON-NLS-1$
|
||||
@Override
|
||||
public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) throws CoreException {
|
||||
if (ast != null) {
|
||||
int offset = hoverRegion.getOffset();
|
||||
int length = hoverRegion.getLength();
|
||||
IASTName name= ast.getNodeSelector(null).findEnclosingName(offset, length);
|
||||
if (name != null) {
|
||||
computeExpressionExtent(name, expressionPosition);
|
||||
}
|
||||
}
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
private void computeExpressionExtent(IASTName name, Position pos) {
|
||||
IASTNode node = name;
|
||||
while (node != null && !(node instanceof IASTExpression) && !(node instanceof IASTDeclaration)) {
|
||||
node = node.getParent();
|
||||
}
|
||||
if (node instanceof IASTExpression) {
|
||||
ExpressionChecker checker = new ExpressionChecker();
|
||||
if (checker.check(node)) {
|
||||
IASTNodeLocation loc = node.getFileLocation();
|
||||
pos.offset = loc.getNodeOffset();
|
||||
pos.length = loc.getNodeLength();
|
||||
}
|
||||
} else {
|
||||
// fallback: use simple name
|
||||
IASTNodeLocation loc = name.getFileLocation();
|
||||
pos.offset = loc.getNodeOffset();
|
||||
pos.length = loc.getNodeLength();
|
||||
}
|
||||
}
|
||||
};
|
||||
job.setPriority(Job.DECORATE);
|
||||
job.setSystem(true);
|
||||
job.schedule();
|
||||
try {
|
||||
job.join();
|
||||
} catch (InterruptedException exc) {
|
||||
job.cancel();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
if (expressionPosition.getLength() > 0) {
|
||||
try {
|
||||
// Get expression text removing comments, obsolete whitespace, etc.
|
||||
StringBuilder result = new StringBuilder();
|
||||
ITypedRegion[] partitions = TextUtilities.computePartitioning(document, ICPartitions.C_PARTITIONING,
|
||||
expressionPosition.offset, expressionPosition.length, false);
|
||||
for (ITypedRegion partition : partitions) {
|
||||
if (IDocument.DEFAULT_CONTENT_TYPE.equals(partition.getType())
|
||||
|| ICPartitions.C_CHARACTER.equals(partition.getType())
|
||||
|| ICPartitions.C_STRING.equals(partition.getType())) {
|
||||
result.append(document.get(partition.getOffset(), partition.getLength()));
|
||||
} else {
|
||||
result.append(' ');
|
||||
}
|
||||
}
|
||||
String text = result.toString().replaceAll("(\\r\\n|\\n|\t| )+", " ").trim(); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
return text;
|
||||
} catch (BadLocationException exc) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the debug context the expression should be evaluated against.
|
||||
* The default implementation returns {@link DebugUITools#getDebugContext()}.
|
||||
*/
|
||||
protected IAdaptable getSelectionAdaptable() {
|
||||
return DebugUITools.getDebugContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the editor this hover is associated with.
|
||||
*/
|
||||
protected final IEditorPart getEditor() {
|
||||
return fEditor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append HTML for the given variable to the given buffer
|
||||
*/
|
||||
private static void appendVariable(StringBuilder buffer, String expression, String value) throws DebugException {
|
||||
if (value.length() > MAX_HOVER_INFO_SIZE)
|
||||
value = value.substring(0, MAX_HOVER_INFO_SIZE) + " ..."; //$NON-NLS-1$
|
||||
buffer.append("<p>"); //$NON-NLS-1$
|
||||
buffer.append("<pre>").append(expression).append("</pre>"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
buffer.append(" = "); //$NON-NLS-1$
|
||||
buffer.append("<b><pre>").append(value).append("</pre></b>"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
buffer.append("</p>"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace any characters in the given String that would confuse an HTML parser with their escape sequences.
|
||||
*/
|
||||
private static String makeHTMLSafe(String string) {
|
||||
StringBuilder buffer = new StringBuilder(string.length());
|
||||
for (int i = 0; i != string.length(); i++) {
|
||||
char ch = string.charAt(i);
|
||||
switch (ch) {
|
||||
case '&':
|
||||
buffer.append("&"); //$NON-NLS-1$
|
||||
break;
|
||||
case '<':
|
||||
buffer.append("<"); //$NON-NLS-1$
|
||||
break;
|
||||
case '>':
|
||||
buffer.append(">"); //$NON-NLS-1$
|
||||
break;
|
||||
case '"':
|
||||
buffer.append("""); //$NON-NLS-1$
|
||||
break;
|
||||
default:
|
||||
buffer.append(ch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue