mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-09 18:56:02 +02:00
Bug 332191 - Expression text hover should use fallback if no parsing information is available
This commit is contained in:
parent
8e592f9a89
commit
acb651e6d6
1 changed files with 274 additions and 124 deletions
|
@ -12,9 +12,13 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.debug.ui.editors;
|
package org.eclipse.cdt.debug.ui.editors;
|
||||||
|
|
||||||
|
import java.util.EmptyStackException;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTComment;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
|
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
|
||||||
|
@ -26,7 +30,14 @@ import org.eclipse.cdt.core.dom.ast.IASTMacroExpansionLocation;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
|
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorElifStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorElseStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorEndifStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfdefStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfndefStatement;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion;
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
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.ICPPASTDeleteExpression;
|
||||||
|
@ -79,7 +90,7 @@ public abstract class AbstractDebugTextHover implements ICEditorTextHover, IText
|
||||||
fValid = true;
|
fValid = true;
|
||||||
node.accept(this);
|
node.accept(this);
|
||||||
return fValid;
|
return fValid;
|
||||||
};
|
}
|
||||||
@Override
|
@Override
|
||||||
public int visit(IASTExpression expression) {
|
public int visit(IASTExpression expression) {
|
||||||
if (expression instanceof IASTFunctionCallExpression) {
|
if (expression instanceof IASTFunctionCallExpression) {
|
||||||
|
@ -97,6 +108,7 @@ public abstract class AbstractDebugTextHover implements ICEditorTextHover, IText
|
||||||
} else if (expression instanceof IASTBinaryExpression) {
|
} else if (expression instanceof IASTBinaryExpression) {
|
||||||
IASTBinaryExpression binaryExpression = (IASTBinaryExpression) expression;
|
IASTBinaryExpression binaryExpression = (IASTBinaryExpression) expression;
|
||||||
switch (binaryExpression.getOperator()) {
|
switch (binaryExpression.getOperator()) {
|
||||||
|
case IASTBinaryExpression.op_assign:
|
||||||
case IASTBinaryExpression.op_binaryAndAssign:
|
case IASTBinaryExpression.op_binaryAndAssign:
|
||||||
case IASTBinaryExpression.op_binaryOrAssign:
|
case IASTBinaryExpression.op_binaryOrAssign:
|
||||||
case IASTBinaryExpression.op_binaryXorAssign:
|
case IASTBinaryExpression.op_binaryXorAssign:
|
||||||
|
@ -160,11 +172,8 @@ public abstract class AbstractDebugTextHover implements ICEditorTextHover, IText
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IRegion getHoverRegion(ITextViewer viewer, int offset) {
|
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)
|
if (viewer != null)
|
||||||
return CDebugUIUtils.findWord(viewer.getDocument(), offset);
|
return CDebugUIUtils.findWord(viewer.getDocument(), offset);
|
||||||
return null;
|
return null;
|
||||||
|
@ -180,7 +189,6 @@ public abstract class AbstractDebugTextHover implements ICEditorTextHover, IText
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the expression text to be evaluated by the debugger.
|
* Compute the expression text to be evaluated by the debugger.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -196,139 +204,281 @@ public abstract class AbstractDebugTextHover implements ICEditorTextHover, IText
|
||||||
IDocument document = textViewer.getDocument();
|
IDocument document = textViewer.getDocument();
|
||||||
if (document == null)
|
if (document == null)
|
||||||
return null;
|
return null;
|
||||||
|
String expression = getExpressionTextFromAST(document, hoverRegion);
|
||||||
|
if (expression == null) {
|
||||||
|
// fallback in case no parsing information is available
|
||||||
|
try {
|
||||||
|
return document.get(hoverRegion.getOffset(), hoverRegion.getLength());
|
||||||
|
} catch (BadLocationException e) {
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
} else if (expression.length() == 0) {
|
||||||
|
// positively invalid expression
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute a valid expression from AST if available.
|
||||||
|
*
|
||||||
|
* @param document
|
||||||
|
* @param hoverRegion
|
||||||
|
* @return a valid expression string, an empty string to indicate an invalid
|
||||||
|
* expression or <code>null</code> if the expression could not be
|
||||||
|
* validated
|
||||||
|
*/
|
||||||
|
private String getExpressionTextFromAST(IDocument document, final IRegion hoverRegion) {
|
||||||
ICElement cElement = CDTUITools.getEditorInputCElement(getEditor().getEditorInput());
|
ICElement cElement = CDTUITools.getEditorInputCElement(getEditor().getEditorInput());
|
||||||
if (cElement instanceof ITranslationUnit) {
|
if (!(cElement instanceof ITranslationUnit)) {
|
||||||
final Position expressionPosition = new Position(0);
|
return null;
|
||||||
SharedASTJob job = new SharedASTJob(CDebugUIMessages.getString("AbstractDebugTextHover.jobName"), (ITranslationUnit) cElement) { //$NON-NLS-1$
|
}
|
||||||
@Override
|
final Position expressionPosition = new Position(0);
|
||||||
public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) throws CoreException {
|
SharedASTJob job = new SharedASTJob(CDebugUIMessages.getString("AbstractDebugTextHover.jobName"), (ITranslationUnit) cElement) { //$NON-NLS-1$
|
||||||
if (ast != null) {
|
@Override
|
||||||
int offset = hoverRegion.getOffset();
|
public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) throws CoreException {
|
||||||
int length = hoverRegion.getLength();
|
if (ast == null) {
|
||||||
IASTName name= ast.getNodeSelector(null).findEnclosingName(offset, length);
|
return Status.CANCEL_STATUS;
|
||||||
if (name != null) {
|
|
||||||
IASTImageLocation imageLoc = name.getImageLocation();
|
|
||||||
int kind = imageLoc.getLocationKind();
|
|
||||||
switch (kind) {
|
|
||||||
case IASTImageLocation.ARGUMENT_TO_MACRO_EXPANSION:
|
|
||||||
computeMacroArgumentExtent(expressionPosition, name);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (name.getParent() instanceof IASTPreprocessorMacroExpansion) {
|
|
||||||
// special case: macro expansion as expression
|
|
||||||
IASTNode node = ast.getNodeSelector(null).findEnclosingNodeInExpansion(imageLoc.getNodeOffset(), imageLoc.getNodeLength());
|
|
||||||
if (node instanceof IASTExpression) {
|
|
||||||
IASTFileLocation exprLoc = node.getFileLocation();
|
|
||||||
if (exprLoc.getNodeOffset() == imageLoc.getNodeOffset()) {
|
|
||||||
computeExpressionExtent(node, expressionPosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
computeExpressionExtent(name, expressionPosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// not a name, but might still be an expression (e.g. this)
|
|
||||||
IASTNode node = ast.getNodeSelector(null).findFirstContainedNode(offset, length);
|
|
||||||
if (node instanceof IASTExpression) {
|
|
||||||
computeExpressionExtent(node, expressionPosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Status.OK_STATUS;
|
|
||||||
}
|
}
|
||||||
|
int offset = hoverRegion.getOffset();
|
||||||
private void computeMacroArgumentExtent(final Position pos, IASTName name) {
|
int length = hoverRegion.getLength();
|
||||||
IASTImageLocation imageLoc = name.getImageLocation();
|
IASTName name= ast.getNodeSelector(null).findEnclosingName(offset, length);
|
||||||
int startOffset = imageLoc.getNodeOffset();
|
if (name != null) {
|
||||||
int endOffset = startOffset + imageLoc.getNodeLength();
|
IASTImageLocation imageLoc = name.getImageLocation();
|
||||||
// do some black magic to consider field reference expressions
|
int kind = imageLoc.getLocationKind();
|
||||||
IASTNode expr = name.getParent();
|
switch (kind) {
|
||||||
int macroOffset = name.getFileLocation().getNodeOffset();
|
case IASTImageLocation.ARGUMENT_TO_MACRO_EXPANSION:
|
||||||
if (expr instanceof IASTFieldReference) {
|
computeMacroArgumentExtent(name, expressionPosition);
|
||||||
IASTExpression ownerExpr= ((IASTFieldReference) expr).getFieldOwner();
|
break;
|
||||||
while (ownerExpr instanceof IASTFieldReference || ownerExpr instanceof IASTArraySubscriptExpression) {
|
default:
|
||||||
if (ownerExpr instanceof IASTArraySubscriptExpression) {
|
if (name.getParent() instanceof IASTPreprocessorMacroExpansion) {
|
||||||
ownerExpr = ((IASTArraySubscriptExpression) ownerExpr).getArrayExpression();
|
// special case: macro expansion as expression
|
||||||
} else {
|
IASTNode node = ast.getNodeSelector(null).findEnclosingNodeInExpansion(imageLoc.getNodeOffset(), imageLoc.getNodeLength());
|
||||||
ownerExpr= ((IASTFieldReference) ownerExpr).getFieldOwner();
|
if (node instanceof IASTExpression) {
|
||||||
|
IASTFileLocation exprLoc = node.getFileLocation();
|
||||||
|
if (exprLoc.getNodeOffset() == imageLoc.getNodeOffset()) {
|
||||||
|
computeExpressionExtent(node, expressionPosition);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
computeExpressionExtent(name, expressionPosition);
|
||||||
}
|
}
|
||||||
if (ownerExpr instanceof IASTIdExpression) {
|
}
|
||||||
IASTName ownerName = ((IASTIdExpression) ownerExpr).getName();
|
} else {
|
||||||
IASTImageLocation ownerImageLoc = ownerName.getImageLocation();
|
// not a name, but might still be an expression (e.g. this or a selected expression)
|
||||||
final int nameOffset= ownerImageLoc.getNodeOffset();
|
IASTNode node = ast.getNodeSelector(null).findEnclosingNode(offset, length);
|
||||||
// offset should be inside macro expansion
|
if (!(node instanceof IASTExpression)) {
|
||||||
if (nameOffset < startOffset && nameOffset > macroOffset) {
|
node = ast.getNodeSelector(null).findFirstContainedNode(offset, length);
|
||||||
startOffset = nameOffset;
|
}
|
||||||
}
|
if (node instanceof IASTExpression) {
|
||||||
|
computeExpressionExtent(node, expressionPosition);
|
||||||
|
} else if (node == null && insideInactiveCode(ast, offset) && !insideComment(ast, offset)) {
|
||||||
|
return Status.CANCEL_STATUS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void computeMacroArgumentExtent(IASTName name, Position pos) {
|
||||||
|
IASTImageLocation imageLoc = name.getImageLocation();
|
||||||
|
int startOffset = imageLoc.getNodeOffset();
|
||||||
|
int endOffset = startOffset + imageLoc.getNodeLength();
|
||||||
|
// do some black magic to consider field reference expressions
|
||||||
|
IASTNode expr = name.getParent();
|
||||||
|
int macroOffset = name.getFileLocation().getNodeOffset();
|
||||||
|
if (expr instanceof IASTFieldReference) {
|
||||||
|
IASTExpression ownerExpr= ((IASTFieldReference) expr).getFieldOwner();
|
||||||
|
while (ownerExpr instanceof IASTFieldReference || ownerExpr instanceof IASTArraySubscriptExpression) {
|
||||||
|
if (ownerExpr instanceof IASTArraySubscriptExpression) {
|
||||||
|
ownerExpr = ((IASTArraySubscriptExpression) ownerExpr).getArrayExpression();
|
||||||
|
} else {
|
||||||
|
ownerExpr= ((IASTFieldReference) ownerExpr).getFieldOwner();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExpressionChecker checker = new ExpressionChecker();
|
if (ownerExpr instanceof IASTIdExpression) {
|
||||||
if (checker.check(expr)) {
|
IASTName ownerName = ((IASTIdExpression) ownerExpr).getName();
|
||||||
pos.offset = startOffset;
|
IASTImageLocation ownerImageLoc = ownerName.getImageLocation();
|
||||||
pos.length = endOffset - startOffset;
|
final int nameOffset= ownerImageLoc.getNodeOffset();
|
||||||
|
// offset should be inside macro expansion
|
||||||
|
if (nameOffset < startOffset && nameOffset > macroOffset) {
|
||||||
|
startOffset = nameOffset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void computeExpressionExtent(IASTNode node0, Position pos) {
|
ExpressionChecker checker = new ExpressionChecker();
|
||||||
IASTNode node = node0;
|
if (checker.check(expr)) {
|
||||||
while (node != null && !(node instanceof IASTExpression) && !(node instanceof IASTDeclaration)) {
|
pos.offset = startOffset;
|
||||||
node = node.getParent();
|
pos.length = endOffset - startOffset;
|
||||||
}
|
}
|
||||||
IASTNodeLocation loc = null;
|
}
|
||||||
if (node instanceof IASTExpression && !(node instanceof IASTIdExpression)) {
|
private void computeExpressionExtent(IASTNode node0, Position pos) {
|
||||||
ExpressionChecker checker = new ExpressionChecker();
|
IASTNode node = node0;
|
||||||
if (checker.check(node)) {
|
while (node != null && !(node instanceof IASTExpression) && !(node instanceof IASTDeclaration)) {
|
||||||
loc = node.getFileLocation();
|
node = node.getParent();
|
||||||
}
|
|
||||||
} else if (node0 instanceof IASTName) {
|
|
||||||
// fallback: use simple name
|
|
||||||
loc = ((IASTName) node0).getImageLocation();
|
|
||||||
if (loc == null) {
|
|
||||||
IASTNodeLocation[] locations = node0.getNodeLocations();
|
|
||||||
// avoid macro expansions
|
|
||||||
if (locations.length == 1 && !(locations[0] instanceof IASTMacroExpansionLocation)) {
|
|
||||||
loc = locations[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (loc != null) {
|
|
||||||
pos.offset = loc.getNodeOffset();
|
|
||||||
pos.length = loc.getNodeLength();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
IASTNodeLocation loc = null;
|
||||||
job.setPriority(Job.SHORT);
|
if (node instanceof IASTExpression && !(node instanceof IASTIdExpression)) {
|
||||||
job.setSystem(true);
|
ExpressionChecker checker = new ExpressionChecker();
|
||||||
job.schedule();
|
if (checker.check(node)) {
|
||||||
try {
|
loc = node.getFileLocation();
|
||||||
job.join();
|
}
|
||||||
} catch (InterruptedException exc) {
|
} else if (node0 instanceof IASTName) {
|
||||||
job.cancel();
|
// fallback: use simple name
|
||||||
Thread.currentThread().interrupt();
|
loc = ((IASTName) node0).getImageLocation();
|
||||||
|
if (loc == null) {
|
||||||
|
IASTNodeLocation[] locations = node0.getNodeLocations();
|
||||||
|
// avoid macro expansions
|
||||||
|
if (locations.length == 1 && !(locations[0] instanceof IASTMacroExpansionLocation)) {
|
||||||
|
loc = locations[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (loc != null) {
|
||||||
|
pos.offset = loc.getNodeOffset();
|
||||||
|
pos.length = loc.getNodeLength();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (expressionPosition.getLength() > 0) {
|
|
||||||
try {
|
private boolean insideInactiveCode(IASTTranslationUnit ast, int offset) {
|
||||||
// Get expression text removing comments, obsolete whitespace, etc.
|
int inactiveCodeStart = -1;
|
||||||
StringBuilder result = new StringBuilder();
|
boolean inInactiveCode = false;
|
||||||
ITypedRegion[] partitions = TextUtilities.computePartitioning(document, ICPartitions.C_PARTITIONING,
|
Stack<Boolean> inactiveCodeStack = new Stack<Boolean>();
|
||||||
expressionPosition.offset, expressionPosition.length, false);
|
|
||||||
for (ITypedRegion partition : partitions) {
|
IASTPreprocessorStatement[] preprocStmts = ast.getAllPreprocessorStatements();
|
||||||
if (IDocument.DEFAULT_CONTENT_TYPE.equals(partition.getType())
|
|
||||||
|| ICPartitions.C_CHARACTER.equals(partition.getType())
|
for (IASTPreprocessorStatement preprocStmt : preprocStmts) {
|
||||||
|| ICPartitions.C_STRING.equals(partition.getType())) {
|
IASTPreprocessorStatement statement = preprocStmt;
|
||||||
result.append(document.get(partition.getOffset(), partition.getLength()));
|
if (!statement.isPartOfTranslationUnitFile()) {
|
||||||
} else {
|
continue;
|
||||||
result.append(' ');
|
}
|
||||||
|
IASTNodeLocation nodeLocation = statement.getFileLocation();
|
||||||
|
if (nodeLocation == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int nodeOffset = nodeLocation.getNodeOffset();
|
||||||
|
int nodeEnd = nodeOffset + nodeLocation.getNodeLength();
|
||||||
|
if (nodeOffset <= offset && offset < nodeEnd) {
|
||||||
|
// inside preprocessor directive
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (statement instanceof IASTPreprocessorIfStatement) {
|
||||||
|
IASTPreprocessorIfStatement ifStmt = (IASTPreprocessorIfStatement)statement;
|
||||||
|
inactiveCodeStack.push(Boolean.valueOf(inInactiveCode));
|
||||||
|
if (!ifStmt.taken()) {
|
||||||
|
if (!inInactiveCode) {
|
||||||
|
inactiveCodeStart = nodeEnd;
|
||||||
|
inInactiveCode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (statement instanceof IASTPreprocessorIfdefStatement) {
|
||||||
|
IASTPreprocessorIfdefStatement ifdefStmt = (IASTPreprocessorIfdefStatement)statement;
|
||||||
|
inactiveCodeStack.push(Boolean.valueOf(inInactiveCode));
|
||||||
|
if (!ifdefStmt.taken()) {
|
||||||
|
if (!inInactiveCode) {
|
||||||
|
inactiveCodeStart = nodeEnd;
|
||||||
|
inInactiveCode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (statement instanceof IASTPreprocessorIfndefStatement) {
|
||||||
|
IASTPreprocessorIfndefStatement ifndefStmt = (IASTPreprocessorIfndefStatement)statement;
|
||||||
|
inactiveCodeStack.push(Boolean.valueOf(inInactiveCode));
|
||||||
|
if (!ifndefStmt.taken()) {
|
||||||
|
if (!inInactiveCode) {
|
||||||
|
inactiveCodeStart = nodeEnd;
|
||||||
|
inInactiveCode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (statement instanceof IASTPreprocessorElseStatement) {
|
||||||
|
IASTPreprocessorElseStatement elseStmt = (IASTPreprocessorElseStatement)statement;
|
||||||
|
if (!elseStmt.taken() && !inInactiveCode) {
|
||||||
|
inactiveCodeStart = nodeEnd;
|
||||||
|
inInactiveCode = true;
|
||||||
|
} else if (elseStmt.taken() && inInactiveCode) {
|
||||||
|
int inactiveCodeEnd = nodeOffset;
|
||||||
|
if (inactiveCodeStart <= offset && offset < inactiveCodeEnd) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
inInactiveCode = false;
|
||||||
|
}
|
||||||
|
} else if (statement instanceof IASTPreprocessorElifStatement) {
|
||||||
|
IASTPreprocessorElifStatement elifStmt = (IASTPreprocessorElifStatement)statement;
|
||||||
|
if (!elifStmt.taken() && !inInactiveCode) {
|
||||||
|
inactiveCodeStart = nodeEnd;
|
||||||
|
inInactiveCode = true;
|
||||||
|
} else if (elifStmt.taken() && inInactiveCode) {
|
||||||
|
int inactiveCodeEnd = nodeOffset;
|
||||||
|
if (inactiveCodeStart <= offset && offset < inactiveCodeEnd) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
inInactiveCode = false;
|
||||||
|
}
|
||||||
|
} else if (statement instanceof IASTPreprocessorEndifStatement) {
|
||||||
|
try {
|
||||||
|
boolean wasInInactiveCode = inactiveCodeStack.pop().booleanValue();
|
||||||
|
if (inInactiveCode && !wasInInactiveCode) {
|
||||||
|
int inactiveCodeEnd = nodeOffset;
|
||||||
|
if (inactiveCodeStart <= offset && offset < inactiveCodeEnd) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inInactiveCode = wasInInactiveCode;
|
||||||
|
}
|
||||||
|
catch (EmptyStackException e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
private boolean insideComment(IASTTranslationUnit ast, int offset) {
|
||||||
|
IASTComment[] comments = ast.getComments();
|
||||||
|
for (IASTComment comment : comments) {
|
||||||
|
if (!comment.isPartOfTranslationUnitFile()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
IASTNodeLocation location = comment.getFileLocation();
|
||||||
|
if (location != null) {
|
||||||
|
if (location.getNodeOffset() <= offset && offset < location.getNodeOffset() + location.getNodeLength()) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String text = result.toString().replaceAll("(\\r\\n|\\n|\t| )+", " ").trim(); //$NON-NLS-1$ //$NON-NLS-2$
|
|
||||||
return text;
|
|
||||||
} catch (BadLocationException exc) {
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
job.setPriority(Job.SHORT);
|
||||||
|
job.setSystem(true);
|
||||||
|
job.schedule();
|
||||||
|
try {
|
||||||
|
job.join();
|
||||||
|
} catch (InterruptedException exc) {
|
||||||
|
job.cancel();
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
if (!job.getResult().isOK()) {
|
||||||
|
// indeterminate result
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
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;
|
// return empty string to indicate invalid expression
|
||||||
|
return ""; //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue