mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Information about syntax between ast-nodes, bug 250251.
This commit is contained in:
parent
10b2bb8da5
commit
dd5413a3a2
18 changed files with 632 additions and 19 deletions
|
@ -18,6 +18,7 @@ import junit.framework.TestSuite;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.ASTSignatureUtil;
|
import org.eclipse.cdt.core.dom.ast.ASTSignatureUtil;
|
||||||
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
|
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.ExpansionOverlapsBoundaryException;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator;
|
import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator;
|
||||||
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;
|
||||||
|
@ -28,6 +29,7 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement;
|
import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTDoStatement;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
|
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
|
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
|
||||||
|
@ -98,6 +100,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
|
||||||
|
import org.eclipse.cdt.core.parser.IToken;
|
||||||
import org.eclipse.cdt.core.parser.ParserLanguage;
|
import org.eclipse.cdt.core.parser.ParserLanguage;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.c.CFunction;
|
import org.eclipse.cdt.internal.core.dom.parser.c.CFunction;
|
||||||
|
@ -5292,4 +5295,138 @@ public class AST2Tests extends AST2BaseTest {
|
||||||
parseAndCheckBindings(getAboveComment(), ParserLanguage.C, true);
|
parseAndCheckBindings(getAboveComment(), ParserLanguage.C, true);
|
||||||
parseAndCheckBindings(getAboveComment(), ParserLanguage.CPP, true);
|
parseAndCheckBindings(getAboveComment(), ParserLanguage.CPP, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #define IF if
|
||||||
|
// #define IF_P if (
|
||||||
|
// #define IF_P_T if (1
|
||||||
|
// #define SEMI_IF ; if
|
||||||
|
// #define IF_COND if (1)
|
||||||
|
// void test() {
|
||||||
|
public void testLeadingSyntax_Bug250251() throws Exception {
|
||||||
|
String code= getAboveComment();
|
||||||
|
|
||||||
|
IASTTranslationUnit tu= parseAndCheckBindings(code + "if (1) {};}");
|
||||||
|
IASTFunctionDefinition f= getDeclaration(tu, 0);
|
||||||
|
IASTIfStatement i = getStatement(f, 0);
|
||||||
|
IASTExpression x= i.getConditionExpression();
|
||||||
|
IToken syntax= x.getLeadingSyntax();
|
||||||
|
checkToken(syntax, "if", -4); syntax= syntax.getNext();
|
||||||
|
checkToken(syntax, "(", -1); syntax= syntax.getNext();
|
||||||
|
assertNull(syntax);
|
||||||
|
|
||||||
|
tu= parseAndCheckBindings(code + "if( 1) {}}");
|
||||||
|
f= getDeclaration(tu, 0); i= getStatement(f, 0); x= i.getConditionExpression();
|
||||||
|
syntax= x.getLeadingSyntax();
|
||||||
|
checkToken(syntax, "if", -5); syntax= syntax.getNext();
|
||||||
|
checkToken(syntax, "(", -3); syntax= syntax.getNext();
|
||||||
|
assertNull(syntax);
|
||||||
|
|
||||||
|
tu= parseAndCheckBindings(code + "if(1) ; else ;}");
|
||||||
|
f= getDeclaration(tu, 0); i= getStatement(f, 0); IASTStatement est= i.getElseClause();
|
||||||
|
syntax= est.getLeadingSyntax();
|
||||||
|
checkToken(syntax, "else", -5); syntax= syntax.getNext();
|
||||||
|
assertNull(syntax);
|
||||||
|
|
||||||
|
tu= parseAndCheckBindings(code + "IF(1) {}}");
|
||||||
|
f= getDeclaration(tu, 0); i= getStatement(f, 0); x= i.getConditionExpression();
|
||||||
|
syntax= x.getLeadingSyntax();
|
||||||
|
checkToken(syntax, "IF", -3); syntax= syntax.getNext();
|
||||||
|
checkToken(syntax, "(", -1); syntax= syntax.getNext();
|
||||||
|
assertNull(syntax);
|
||||||
|
|
||||||
|
tu= parseAndCheckBindings(code + "IF_P 1) {}}");
|
||||||
|
f= getDeclaration(tu, 0); i= getStatement(f, 0); x= i.getConditionExpression();
|
||||||
|
syntax= x.getLeadingSyntax();
|
||||||
|
checkToken(syntax, "IF_P", -5); syntax= syntax.getNext();
|
||||||
|
assertNull(syntax);
|
||||||
|
|
||||||
|
tu= parseAndCheckBindings(code + "IF_P_T ) {}}");
|
||||||
|
f= getDeclaration(tu, 0); i= getStatement(f, 0); x= i.getConditionExpression();
|
||||||
|
try {
|
||||||
|
syntax= x.getLeadingSyntax();
|
||||||
|
fail();
|
||||||
|
} catch (ExpansionOverlapsBoundaryException e) {}
|
||||||
|
|
||||||
|
tu= parseAndCheckBindings(code + "SEMI_IF (1) {}}");
|
||||||
|
f= getDeclaration(tu, 0); i= getStatement(f, 1); x= i.getConditionExpression();
|
||||||
|
try {
|
||||||
|
syntax= x.getLeadingSyntax();
|
||||||
|
fail();
|
||||||
|
} catch (ExpansionOverlapsBoundaryException e) {}
|
||||||
|
|
||||||
|
tu= parseAndCheckBindings(code + "IF_COND {}}");
|
||||||
|
f= getDeclaration(tu, 0); i= getStatement(f, 0); x= i.getConditionExpression();
|
||||||
|
try {
|
||||||
|
syntax= x.getLeadingSyntax();
|
||||||
|
fail();
|
||||||
|
} catch (ExpansionOverlapsBoundaryException e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #define P(x) )
|
||||||
|
// #define BLOCK() {}
|
||||||
|
// #define T_P 1)
|
||||||
|
// #define P_BLOCK ){}
|
||||||
|
// #define IF_COND if (1)
|
||||||
|
// void test() {
|
||||||
|
public void testTrailingSyntax_Bug250251() throws Exception {
|
||||||
|
String code= getAboveComment();
|
||||||
|
|
||||||
|
IASTTranslationUnit tu= parseAndCheckBindings(code + "if (1) {};}");
|
||||||
|
IASTFunctionDefinition f= getDeclaration(tu, 0);
|
||||||
|
IASTIfStatement i = getStatement(f, 0);
|
||||||
|
IASTExpression x= i.getConditionExpression();
|
||||||
|
IToken syntax= x.getTrailingSyntax();
|
||||||
|
checkToken(syntax, ")", 0); syntax= syntax.getNext();
|
||||||
|
assertNull(syntax);
|
||||||
|
|
||||||
|
tu= parseAndCheckBindings(code + "do {} while(1 );}");
|
||||||
|
f= getDeclaration(tu, 0); IASTDoStatement dstmt= getStatement(f, 0); x= dstmt.getCondition();
|
||||||
|
syntax= x.getTrailingSyntax();
|
||||||
|
checkToken(syntax, ")", 1); syntax= syntax.getNext();
|
||||||
|
checkToken(syntax, ";", 2); syntax= syntax.getNext();
|
||||||
|
assertNull(syntax);
|
||||||
|
|
||||||
|
|
||||||
|
tu= parseAndCheckBindings(code + "if(1 ) BLOCK()}");
|
||||||
|
f= getDeclaration(tu, 0); i= getStatement(f, 0); x= i.getConditionExpression();
|
||||||
|
syntax= x.getTrailingSyntax();
|
||||||
|
checkToken(syntax, ")", 1); syntax= syntax.getNext();
|
||||||
|
assertNull(syntax);
|
||||||
|
|
||||||
|
tu= parseAndCheckBindings(code + "if(1 P(0) {}}");
|
||||||
|
f= getDeclaration(tu, 0); i= getStatement(f, 0); x= i.getConditionExpression();
|
||||||
|
syntax= x.getTrailingSyntax();
|
||||||
|
checkToken(syntax, "P", 1); syntax= syntax.getNext();
|
||||||
|
checkToken(syntax, "(", 2); syntax= syntax.getNext();
|
||||||
|
checkToken(syntax, "0", 3); syntax= syntax.getNext();
|
||||||
|
checkToken(syntax, ")", 4); syntax= syntax.getNext();
|
||||||
|
assertNull(syntax);
|
||||||
|
|
||||||
|
tu= parseAndCheckBindings(code + "if (T_P {}}");
|
||||||
|
f= getDeclaration(tu, 0); i= getStatement(f, 0); x= i.getConditionExpression();
|
||||||
|
try {
|
||||||
|
syntax= x.getTrailingSyntax();
|
||||||
|
fail();
|
||||||
|
} catch (ExpansionOverlapsBoundaryException e) {}
|
||||||
|
|
||||||
|
tu= parseAndCheckBindings(code + "if (1 P_BLOCK }");
|
||||||
|
f= getDeclaration(tu, 0); i= getStatement(f, 0); x= i.getConditionExpression();
|
||||||
|
try {
|
||||||
|
syntax= x.getTrailingSyntax();
|
||||||
|
fail();
|
||||||
|
} catch (ExpansionOverlapsBoundaryException e) {}
|
||||||
|
|
||||||
|
tu= parseAndCheckBindings(code + "IF_COND {}}");
|
||||||
|
f= getDeclaration(tu, 0); i= getStatement(f, 0); x= i.getConditionExpression();
|
||||||
|
try {
|
||||||
|
syntax= x.getTrailingSyntax();
|
||||||
|
fail();
|
||||||
|
} catch (ExpansionOverlapsBoundaryException e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkToken(IToken token, String image, int offset) {
|
||||||
|
assertEquals(image, token.getImage());
|
||||||
|
assertEquals(offset, token.getOffset());
|
||||||
|
assertEquals(image.length(), token.getLength());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit;
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner.ILocationCtx;
|
import org.eclipse.cdt.internal.core.parser.scanner.ILocationCtx;
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner.ImageLocationInfo;
|
import org.eclipse.cdt.internal.core.parser.scanner.ImageLocationInfo;
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner.LocationMap;
|
import org.eclipse.cdt.internal.core.parser.scanner.LocationMap;
|
||||||
|
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
|
||||||
|
|
||||||
public class LocationMapTests extends BaseTestCase {
|
public class LocationMapTests extends BaseTestCase {
|
||||||
public class Loc implements IASTFileLocation {
|
public class Loc implements IASTFileLocation {
|
||||||
|
@ -102,7 +103,7 @@ public class LocationMapTests extends BaseTestCase {
|
||||||
@Override
|
@Override
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
fLocationMap= new LocationMap();
|
fLocationMap= new LocationMap(new LexerOptions());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -116,6 +116,38 @@ public abstract class ASTVisitor {
|
||||||
*/
|
*/
|
||||||
public boolean shouldVisitTemplateParameters = false;
|
public boolean shouldVisitTemplateParameters = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a visitor that does not visit any kind of node per default.
|
||||||
|
*/
|
||||||
|
public ASTVisitor() {
|
||||||
|
this(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a visitor.
|
||||||
|
* @param visitNodes whether visitor is setup to visit all nodes per default.
|
||||||
|
* @since 5.1
|
||||||
|
*/
|
||||||
|
public ASTVisitor(boolean visitNodes) {
|
||||||
|
shouldVisitArrayModifiers= visitNodes;
|
||||||
|
shouldVisitBaseSpecifiers= visitNodes;
|
||||||
|
shouldVisitDeclarations= visitNodes;
|
||||||
|
shouldVisitDeclarators= visitNodes;
|
||||||
|
shouldVisitDeclSpecifiers= visitNodes;
|
||||||
|
shouldVisitDesignators= visitNodes;
|
||||||
|
shouldVisitEnumerators= visitNodes;
|
||||||
|
shouldVisitExpressions= visitNodes;
|
||||||
|
shouldVisitInitializers= visitNodes;
|
||||||
|
shouldVisitNames= visitNodes;
|
||||||
|
shouldVisitNamespaces= visitNodes;
|
||||||
|
shouldVisitParameterDeclarations= visitNodes;
|
||||||
|
shouldVisitProblems= visitNodes;
|
||||||
|
shouldVisitStatements= visitNodes;
|
||||||
|
shouldVisitTemplateParameters= visitNodes;
|
||||||
|
shouldVisitTranslationUnit= visitNodes;
|
||||||
|
shouldVisitTypeIds= visitNodes;
|
||||||
|
}
|
||||||
|
|
||||||
// visit methods
|
// visit methods
|
||||||
public int visit(IASTTranslationUnit tu) {
|
public int visit(IASTTranslationUnit tu) {
|
||||||
return PROCESS_CONTINUE;
|
return PROCESS_CONTINUE;
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008 Wind River Systems, Inc. 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:
|
||||||
|
* Markus Schorn - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.core.dom.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See {@link IASTNode#getTrailingSyntax()} and {@link IASTNode#getLeadingSyntax()}.
|
||||||
|
* @since 5.1
|
||||||
|
*/
|
||||||
|
public class ExpansionOverlapsBoundaryException extends Exception {
|
||||||
|
|
||||||
|
}
|
|
@ -6,16 +6,18 @@
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* IBM - Initial API and implementation
|
* Doug Schaefer - Initial API and implementation
|
||||||
* Markus Schorn (Wind River Systems)
|
* Markus Schorn (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.core.dom.ast;
|
package org.eclipse.cdt.core.dom.ast;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.parser.IToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the root node in the physical AST. A physical node represents a chunk
|
* This is the root node in the physical AST. A physical node represents a chunk
|
||||||
* of text in the source program.
|
* of text in the source program.
|
||||||
*
|
*
|
||||||
* @author Doug Schaefer
|
* @noimplement This interface is not intended to be implemented by clients.
|
||||||
*/
|
*/
|
||||||
public interface IASTNode {
|
public interface IASTNode {
|
||||||
|
|
||||||
|
@ -128,4 +130,48 @@ public interface IASTNode {
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public boolean contains(IASTNode node);
|
public boolean contains(IASTNode node);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the tokens that can be found between this node and its left sibling (or the
|
||||||
|
* beginning of the parent, if there is no left sibling). The tokens are obtained
|
||||||
|
* from the lexer, no preprocessing is performed.
|
||||||
|
* The offsets of the tokens are relative to the file-offset of this node.
|
||||||
|
* <p> <b>Examples</b> looking at the condition of if-statements:
|
||||||
|
* <pre>
|
||||||
|
* #define IF if
|
||||||
|
* #define IF_P if (
|
||||||
|
* #define IF_P_T if (true
|
||||||
|
* #define SEMI_IF ; if
|
||||||
|
* #define IF_COND if (true)
|
||||||
|
* void test() {
|
||||||
|
* if (true) {} // leading syntax: 'if ('
|
||||||
|
* IF (true) {} // leading syntax: 'IF ('
|
||||||
|
* IF_P true) {} // leading syntax: 'IF_P'
|
||||||
|
* IF_P_T ) {} // throws ExpansionOverlapsBoundaryException
|
||||||
|
* SEMI_IF (true) {} // throws ExpansionOverlapsBoundaryException
|
||||||
|
* IF_COND // throws ExpansionOverlapsBoundaryException
|
||||||
|
* </pre>
|
||||||
|
* @return a chain of tokens or <code>null</code>, if there are none.
|
||||||
|
* @throws ExpansionOverlapsBoundaryException if one of the boundaries of the leading syntax is
|
||||||
|
* overlapped by a macro-expansion.
|
||||||
|
* @throws UnsupportedOperationException if invoked on preprocessor nodes, or nodes that are not
|
||||||
|
* part of a translation unit.
|
||||||
|
* @since 5.1
|
||||||
|
*/
|
||||||
|
public IToken getLeadingSyntax() throws ExpansionOverlapsBoundaryException, UnsupportedOperationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the tokens that can be found between this node and its right sibling (or the
|
||||||
|
* end of the parent, if there is no right sibling). The tokens are obtained from the lexer,
|
||||||
|
* no preprocessing is performed.
|
||||||
|
* The offsets of the tokens are relative to the file-offset of the end of this node.
|
||||||
|
* <p> For examples see {@link #getLeadingSyntax()}.
|
||||||
|
* @return a chain of tokens or <code>null</code>, if there are none.
|
||||||
|
* @throws ExpansionOverlapsBoundaryException if one of the boundaries of the trailing syntax is
|
||||||
|
* overlapped by a macro-expansion.
|
||||||
|
* @throws UnsupportedOperationException if invoked on preprocessor nodes, or nodes that are not
|
||||||
|
* part of a translation unit.
|
||||||
|
* @since 5.1
|
||||||
|
*/
|
||||||
|
public IToken getTrailingSyntax() throws ExpansionOverlapsBoundaryException, UnsupportedOperationException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,34 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2005, 2007 IBM Corporation and others.
|
* Copyright (c) 2005, 2008 IBM Corporation and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* IBM Rational Software - Initial API and implementation
|
* John Camelon - Initial API and implementation
|
||||||
* Markus Schorn (Wind River Systems)
|
* Markus Schorn (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser;
|
package org.eclipse.cdt.internal.core.dom.parser;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
|
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
|
||||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.ExpansionOverlapsBoundaryException;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTImageLocation;
|
import org.eclipse.cdt.core.dom.ast.IASTImageLocation;
|
||||||
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.IASTTranslationUnit;
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
|
import org.eclipse.cdt.core.parser.IToken;
|
||||||
|
import org.eclipse.cdt.core.parser.OffsetLimitReachedException;
|
||||||
|
import org.eclipse.cdt.internal.core.parser.scanner.ILexerLog;
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver;
|
import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver;
|
||||||
|
import org.eclipse.cdt.internal.core.parser.scanner.Lexer;
|
||||||
|
import org.eclipse.cdt.internal.core.parser.scanner.Token;
|
||||||
|
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author jcamelon
|
* Base class for all non-preprocessor nodes in the AST.
|
||||||
*/
|
*/
|
||||||
public abstract class ASTNode implements IASTNode {
|
public abstract class ASTNode implements IASTNode {
|
||||||
|
|
||||||
|
@ -182,4 +189,98 @@ public abstract class ASTNode implements IASTNode {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IToken getLeadingSyntax() throws ExpansionOverlapsBoundaryException {
|
||||||
|
int left= getBoundary(-1);
|
||||||
|
return getSyntax(left, offset, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IToken getTrailingSyntax() throws ExpansionOverlapsBoundaryException {
|
||||||
|
int right= getBoundary(1);
|
||||||
|
return getSyntax(offset+length, right, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the sequence number of the boundary of the leading/trailing syntax.
|
||||||
|
*/
|
||||||
|
private int getBoundary(int direction) {
|
||||||
|
ASTNodeSearch visitor= new ASTNodeSearch(this);
|
||||||
|
IASTNode sib= direction < 0 ? visitor.findLeftSibling() : visitor.findRightSibling();
|
||||||
|
if (sib == null) {
|
||||||
|
direction= -direction;
|
||||||
|
sib= getParent();
|
||||||
|
}
|
||||||
|
if (sib instanceof ASTNode) {
|
||||||
|
ASTNode astNode= (ASTNode) sib;
|
||||||
|
int offset= astNode.getOffset();
|
||||||
|
if (direction < 0) {
|
||||||
|
offset+= astNode.getLength();
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
// no parent
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private IToken getSyntax(int fromSequenceNumber, int nextSequenceNumber, int direction) throws ExpansionOverlapsBoundaryException {
|
||||||
|
final IASTTranslationUnit tu= getTranslationUnit();
|
||||||
|
if (!(tu instanceof ASTNode))
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
|
||||||
|
ILocationResolver lr= (ILocationResolver) tu.getAdapter(ILocationResolver.class);
|
||||||
|
if (lr == null)
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
|
||||||
|
int endSequenceNumber= lr.convertToSequenceEndNumber(nextSequenceNumber);
|
||||||
|
IASTFileLocation total= lr.getMappedFileLocation(fromSequenceNumber, endSequenceNumber-fromSequenceNumber);
|
||||||
|
IASTFileLocation myfloc= getFileLocation();
|
||||||
|
if (total == null || myfloc == null)
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
|
||||||
|
if (!total.getFileName().equals(myfloc.getFileName()))
|
||||||
|
throw new ExpansionOverlapsBoundaryException();
|
||||||
|
|
||||||
|
if (fromSequenceNumber > 0) {
|
||||||
|
IASTFileLocation fl= lr.getMappedFileLocation(fromSequenceNumber-1, endSequenceNumber-fromSequenceNumber+1);
|
||||||
|
if (fl.getFileName().equals(total.getFileName()) && fl.getNodeOffset() == total.getNodeOffset())
|
||||||
|
throw new ExpansionOverlapsBoundaryException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endSequenceNumber < ((ASTNode) tu).getOffset() + ((ASTNode) tu).getLength()) {
|
||||||
|
IASTFileLocation fl= lr.getMappedFileLocation(fromSequenceNumber, nextSequenceNumber-fromSequenceNumber+1);
|
||||||
|
if (fl.getFileName().equals(total.getFileName()) && fl.getNodeLength() == total.getNodeLength())
|
||||||
|
throw new ExpansionOverlapsBoundaryException();
|
||||||
|
}
|
||||||
|
|
||||||
|
int adjustment= total.getNodeOffset() - myfloc.getNodeOffset();
|
||||||
|
if (direction > 0) {
|
||||||
|
adjustment-= myfloc.getNodeLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
char[] txt= lr.getUnpreprocessedSignature(total);
|
||||||
|
Lexer lex= new Lexer(txt, (LexerOptions) tu.getAdapter(LexerOptions.class), ILexerLog.NULL, null);
|
||||||
|
try {
|
||||||
|
Token result= lex.nextToken();
|
||||||
|
if (result.getType() == IToken.tEND_OF_INPUT)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Token last= result;
|
||||||
|
for(;;) {
|
||||||
|
int offset= last.getOffset() + adjustment;
|
||||||
|
int endOffset= last.getEndOffset() + adjustment;
|
||||||
|
last.setOffset(offset, endOffset);
|
||||||
|
|
||||||
|
Token t= lex.nextToken();
|
||||||
|
if (t.getType() == IToken.tEND_OF_INPUT)
|
||||||
|
break;
|
||||||
|
last.setNext(t);
|
||||||
|
last= t;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} catch (OffsetLimitReachedException e) {
|
||||||
|
// does not happen without using content assist limit
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,191 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008 Wind River Systems, Inc. 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:
|
||||||
|
* Markus Schorn - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.internal.core.dom.parser;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTArrayModifier;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTProblem;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.c.ICASTDesignator;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.c.ICASTVisitor;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisitor;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class to search for siblings of an ast node
|
||||||
|
*/
|
||||||
|
public class ASTNodeSearch extends ASTVisitor implements ICASTVisitor, ICPPASTVisitor {
|
||||||
|
private static final int LEFT = 0;
|
||||||
|
private static final int RIGHT= 1;
|
||||||
|
private int fMode;
|
||||||
|
private IASTNode fLeft;
|
||||||
|
private IASTNode fRight;
|
||||||
|
private final IASTNode fNode;
|
||||||
|
private final IASTNode fParent;
|
||||||
|
|
||||||
|
public ASTNodeSearch(IASTNode node) {
|
||||||
|
super(true);
|
||||||
|
fNode= node;
|
||||||
|
fParent= node.getParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTNode findLeftSibling() {
|
||||||
|
if (fParent == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
fMode= LEFT;
|
||||||
|
fLeft= fRight= null;
|
||||||
|
fParent.accept(this);
|
||||||
|
return fLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTNode findRightSibling() {
|
||||||
|
if (fParent == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
fMode= RIGHT;
|
||||||
|
fLeft= fRight= null;
|
||||||
|
fParent.accept(this);
|
||||||
|
return fRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int process(IASTNode node) {
|
||||||
|
if (node == fParent)
|
||||||
|
return PROCESS_CONTINUE;
|
||||||
|
|
||||||
|
switch(fMode) {
|
||||||
|
case LEFT:
|
||||||
|
if (node == fNode)
|
||||||
|
return PROCESS_ABORT;
|
||||||
|
fLeft= node;
|
||||||
|
return PROCESS_SKIP;
|
||||||
|
case RIGHT:
|
||||||
|
if (node == fNode) {
|
||||||
|
fLeft= fNode;
|
||||||
|
} else if (fLeft != null) {
|
||||||
|
fRight= node;
|
||||||
|
return PROCESS_ABORT;
|
||||||
|
}
|
||||||
|
return PROCESS_SKIP;
|
||||||
|
}
|
||||||
|
return PROCESS_SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int visit(ICASTDesignator designator) {
|
||||||
|
return process(designator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTArrayModifier arrayModifier) {
|
||||||
|
return process(arrayModifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTDeclaration declaration) {
|
||||||
|
return process(declaration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTDeclarator declarator) {
|
||||||
|
return process(declarator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTDeclSpecifier declSpec) {
|
||||||
|
return process(declSpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTEnumerator enumerator) {
|
||||||
|
return process(enumerator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTExpression expression) {
|
||||||
|
return process(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTInitializer initializer) {
|
||||||
|
return process(initializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTName name) {
|
||||||
|
return process(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTParameterDeclaration parameterDeclaration) {
|
||||||
|
return process(parameterDeclaration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTProblem problem) {
|
||||||
|
return process(problem);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTStatement statement) {
|
||||||
|
return process(statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTTranslationUnit tu) {
|
||||||
|
return process(tu);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTTypeId typeId) {
|
||||||
|
return process(typeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int visit(ICPPASTBaseSpecifier baseSpecifier) {
|
||||||
|
return process(baseSpecifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int visit(ICPPASTNamespaceDefinition namespaceDefinition) {
|
||||||
|
return process(namespaceDefinition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int visit(ICPPASTTemplateParameter templateParameter) {
|
||||||
|
return process(templateParameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int leave(ICASTDesignator designator) {
|
||||||
|
return PROCESS_CONTINUE;
|
||||||
|
}
|
||||||
|
public int leave(ICPPASTBaseSpecifier baseSpecifier) {
|
||||||
|
return PROCESS_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int leave(ICPPASTNamespaceDefinition namespaceDefinition) {
|
||||||
|
return PROCESS_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int leave(ICPPASTTemplateParameter templateParameter) {
|
||||||
|
return PROCESS_CONTINUE;
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,6 +37,7 @@ import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver;
|
import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver;
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner.ISkippedIndexedFilesListener;
|
import org.eclipse.cdt.internal.core.parser.scanner.ISkippedIndexedFilesListener;
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner.IncludeFileContent;
|
import org.eclipse.cdt.internal.core.parser.scanner.IncludeFileContent;
|
||||||
|
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -294,6 +295,9 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
|
||||||
if (adapter.isAssignableFrom(IIndexFileSet.class)) {
|
if (adapter.isAssignableFrom(IIndexFileSet.class)) {
|
||||||
return fIndexFileSet;
|
return fIndexFileSet;
|
||||||
}
|
}
|
||||||
|
if (adapter.isAssignableFrom(LexerOptions.class)) {
|
||||||
|
return fLocationResolver.getLexerOptions();
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
||||||
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.IASTTranslationUnit;
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
|
import org.eclipse.cdt.core.parser.IToken;
|
||||||
import org.eclipse.cdt.internal.core.dom.rewrite.astwriter.ASTWriterVisitor;
|
import org.eclipse.cdt.internal.core.dom.rewrite.astwriter.ASTWriterVisitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -78,4 +79,12 @@ public class ASTLiteralNode implements IASTNode {
|
||||||
|
|
||||||
public void setPropertyInParent(ASTNodeProperty property) {
|
public void setPropertyInParent(ASTNodeProperty property) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IToken getLeadingSyntax() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IToken getTrailingSyntax() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
|
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree;
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree.IASTInclusionNode;
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree.IASTInclusionNode;
|
||||||
|
import org.eclipse.cdt.core.parser.IToken;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNodeSpecification;
|
import org.eclipse.cdt.internal.core.dom.parser.ASTNodeSpecification;
|
||||||
|
@ -77,6 +78,16 @@ abstract class ASTPreprocessorNode extends ASTNode {
|
||||||
void findNode(ASTNodeSpecification<?> nodeSpec) {
|
void findNode(ASTNodeSpecification<?> nodeSpec) {
|
||||||
nodeSpec.visit(this);
|
nodeSpec.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IToken getLeadingSyntax() throws UnsupportedOperationException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IToken getTrailingSyntax() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
||||||
|
|
||||||
// state information
|
// state information
|
||||||
private final CharArrayMap<PreprocessorMacro> fMacroDictionary = new CharArrayMap<PreprocessorMacro>(512);
|
private final CharArrayMap<PreprocessorMacro> fMacroDictionary = new CharArrayMap<PreprocessorMacro>(512);
|
||||||
private final LocationMap fLocationMap = new LocationMap();
|
private final LocationMap fLocationMap;
|
||||||
|
|
||||||
/** Set of already included files */
|
/** Set of already included files */
|
||||||
private final HashSet<String> fAllIncludedFiles= new HashSet<String>();
|
private final HashSet<String> fAllIncludedFiles= new HashSet<String>();
|
||||||
|
@ -161,6 +161,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
||||||
fLexOptions.fSupportAtSignInIdentifiers= configuration.supportAtSignInIdentifiers();
|
fLexOptions.fSupportAtSignInIdentifiers= configuration.supportAtSignInIdentifiers();
|
||||||
fLexOptions.fSupportMinAndMax = configuration.supportMinAndMaxOperators();
|
fLexOptions.fSupportMinAndMax = configuration.supportMinAndMaxOperators();
|
||||||
fLexOptions.fSupportSlashPercentComments= configuration.supportSlashPercentComments();
|
fLexOptions.fSupportSlashPercentComments= configuration.supportSlashPercentComments();
|
||||||
|
fLocationMap= new LocationMap(fLexOptions);
|
||||||
fKeywords= new CharArrayIntMap(40, -1);
|
fKeywords= new CharArrayIntMap(40, -1);
|
||||||
fPPKeywords= new CharArrayIntMap(40, -1);
|
fPPKeywords= new CharArrayIntMap(40, -1);
|
||||||
configureKeywords(language, configuration);
|
configureKeywords(language, configuration);
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
|
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree;
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNodeSpecification;
|
import org.eclipse.cdt.internal.core.dom.parser.ASTNodeSpecification;
|
||||||
|
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -163,4 +164,16 @@ public interface ILocationResolver {
|
||||||
* @since 5.0
|
* @since 5.0
|
||||||
*/
|
*/
|
||||||
IASTPreprocessorMacroExpansion[] getMacroExpansions(IASTFileLocation loc);
|
IASTPreprocessorMacroExpansion[] getMacroExpansions(IASTFileLocation loc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If you want to use the sequence number of an ast-node as the end of a previous node,
|
||||||
|
* it needs to be adjusted, because gaps are used for the encoding of directives.
|
||||||
|
* @return the adjusted sequence number, to be used as end-number
|
||||||
|
*/
|
||||||
|
int convertToSequenceEndNumber(int sequenceNumber);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the lexer options that have been used by the preprocessor.
|
||||||
|
*/
|
||||||
|
LexerOptions getLexerOptions();
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,6 +98,14 @@ abstract class LocationCtx implements ILocationCtx {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int convertToSequenceEndNumber(int sequenceNumber) {
|
||||||
|
// if the sequence number is the beginning of this context, skip the denotation of this
|
||||||
|
// context in the parent.
|
||||||
|
if (sequenceNumber == fSequenceNumber)
|
||||||
|
return sequenceNumber - fEndOffsetInParent + fOffsetInParent;
|
||||||
|
return sequenceNumber;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the minimal file location containing the specified sequence number range, assuming
|
* Returns the minimal file location containing the specified sequence number range, assuming
|
||||||
* that it is contained in this context.
|
* that it is contained in this context.
|
||||||
|
|
|
@ -109,6 +109,21 @@ class LocationCtxContainer extends LocationCtx {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int convertToSequenceEndNumber(int sequenceNumber) {
|
||||||
|
// try to delegate to a child.
|
||||||
|
final LocationCtx child= findChildLessOrEqualThan(sequenceNumber, false);
|
||||||
|
if (child != null)
|
||||||
|
sequenceNumber= child.convertToSequenceEndNumber(sequenceNumber);
|
||||||
|
|
||||||
|
// if the potentially converted sequence number is the beginning of this context,
|
||||||
|
// skip the denotation of this context in the parent.
|
||||||
|
if (sequenceNumber == fSequenceNumber)
|
||||||
|
return sequenceNumber - fEndOffsetInParent + fOffsetInParent;
|
||||||
|
|
||||||
|
return sequenceNumber;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ASTFileLocation findMappedFileLocation(int sequenceNumber, int length) {
|
public ASTFileLocation findMappedFileLocation(int sequenceNumber, int length) {
|
||||||
// try to delegate to a child.
|
// try to delegate to a child.
|
||||||
|
|
|
@ -34,6 +34,7 @@ import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNodeSpecification;
|
import org.eclipse.cdt.internal.core.dom.parser.ASTNodeSpecification;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTProblem;
|
import org.eclipse.cdt.internal.core.dom.parser.ASTProblem;
|
||||||
|
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the offsets relative to various contexts to the global sequence number. Also creates and stores
|
* Converts the offsets relative to various contexts to the global sequence number. Also creates and stores
|
||||||
|
@ -43,6 +44,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTProblem;
|
||||||
public class LocationMap implements ILocationResolver {
|
public class LocationMap implements ILocationResolver {
|
||||||
private static final IASTName[] EMPTY_NAMES = {};
|
private static final IASTName[] EMPTY_NAMES = {};
|
||||||
|
|
||||||
|
private final LexerOptions fLexerOptions;
|
||||||
private String fTranslationUnitPath;
|
private String fTranslationUnitPath;
|
||||||
private IASTTranslationUnit fTranslationUnit;
|
private IASTTranslationUnit fTranslationUnit;
|
||||||
|
|
||||||
|
@ -60,6 +62,14 @@ public class LocationMap implements ILocationResolver {
|
||||||
private IdentityHashMap<IBinding, IASTPreprocessorMacroDefinition> fMacroDefinitionMap= null;
|
private IdentityHashMap<IBinding, IASTPreprocessorMacroDefinition> fMacroDefinitionMap= null;
|
||||||
private List<ISkippedIndexedFilesListener> fSkippedFilesListeners= new ArrayList<ISkippedIndexedFilesListener>();
|
private List<ISkippedIndexedFilesListener> fSkippedFilesListeners= new ArrayList<ISkippedIndexedFilesListener>();
|
||||||
|
|
||||||
|
public LocationMap(LexerOptions lexOptions) {
|
||||||
|
fLexerOptions= lexOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LexerOptions getLexerOptions() {
|
||||||
|
return fLexerOptions;
|
||||||
|
}
|
||||||
|
|
||||||
public void registerPredefinedMacro(IMacroBinding macro) {
|
public void registerPredefinedMacro(IMacroBinding macro) {
|
||||||
registerPredefinedMacro(macro, null, -1);
|
registerPredefinedMacro(macro, null, -1);
|
||||||
}
|
}
|
||||||
|
@ -392,6 +402,10 @@ public class LocationMap implements ILocationResolver {
|
||||||
return fRootContext.findMappedFileLocation(sequenceNumber, length);
|
return fRootContext.findMappedFileLocation(sequenceNumber, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int convertToSequenceEndNumber(int sequenceNumber) {
|
||||||
|
return fRootContext.convertToSequenceEndNumber(sequenceNumber);
|
||||||
|
}
|
||||||
|
|
||||||
public char[] getUnpreprocessedSignature(IASTFileLocation loc) {
|
public char[] getUnpreprocessedSignature(IASTFileLocation loc) {
|
||||||
ASTFileLocation floc= convertFileLocation(loc);
|
ASTFileLocation floc= convertFileLocation(loc);
|
||||||
if (floc == null) {
|
if (floc == null) {
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
|
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
|
||||||
import org.eclipse.cdt.core.dom.rewrite.MacroExpansionExplorer;
|
import org.eclipse.cdt.core.dom.rewrite.MacroExpansionExplorer;
|
||||||
|
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
|
||||||
import org.eclipse.jface.text.IRegion;
|
import org.eclipse.jface.text.IRegion;
|
||||||
import org.eclipse.text.edits.ReplaceEdit;
|
import org.eclipse.text.edits.ReplaceEdit;
|
||||||
|
|
||||||
|
@ -99,7 +100,8 @@ public class MultiMacroExpansionExplorer extends MacroExpansionExplorer {
|
||||||
fBoundaries[++bidx]= to;
|
fBoundaries[++bidx]= to;
|
||||||
fDelegates[++didx]= new SingleMacroExpansionExplorer(new String(fSource, from, to-from),
|
fDelegates[++didx]= new SingleMacroExpansionExplorer(new String(fSource, from, to-from),
|
||||||
refs.toArray(new IASTName[refs.size()]), fMacroLocations,
|
refs.toArray(new IASTName[refs.size()]), fMacroLocations,
|
||||||
fFilePath, refLoc.getStartingLineNumber(), isPPCond);
|
fFilePath, refLoc.getStartingLineNumber(), isPPCond,
|
||||||
|
(LexerOptions) tu.getAdapter(LexerOptions.class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fBoundaries[++bidx]= fSource.length;
|
fBoundaries[++bidx]= fSource.length;
|
||||||
|
|
|
@ -26,12 +26,6 @@ import org.eclipse.text.edits.ReplaceEdit;
|
||||||
* @since 5.0
|
* @since 5.0
|
||||||
*/
|
*/
|
||||||
public class SingleMacroExpansionExplorer extends MacroExpansionExplorer {
|
public class SingleMacroExpansionExplorer extends MacroExpansionExplorer {
|
||||||
|
|
||||||
private static final LexerOptions LEX_OPTIONS= new LexerOptions();
|
|
||||||
static {
|
|
||||||
LEX_OPTIONS.fCreateImageLocations= false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final String fInput;
|
private final String fInput;
|
||||||
private final CharArrayMap<PreprocessorMacro> fDictionary;
|
private final CharArrayMap<PreprocessorMacro> fDictionary;
|
||||||
private MacroExpansionStep fFullExpansion;
|
private MacroExpansionStep fFullExpansion;
|
||||||
|
@ -40,16 +34,19 @@ public class SingleMacroExpansionExplorer extends MacroExpansionExplorer {
|
||||||
private final int fLineNumber;
|
private final int fLineNumber;
|
||||||
private final Map<IMacroBinding, IASTFileLocation> fMacroLocationMap;
|
private final Map<IMacroBinding, IASTFileLocation> fMacroLocationMap;
|
||||||
private final boolean fIsPPCondition;
|
private final boolean fIsPPCondition;
|
||||||
|
private final LexerOptions fLexerOptions;
|
||||||
|
|
||||||
public SingleMacroExpansionExplorer(String input, IASTName[] refs,
|
public SingleMacroExpansionExplorer(String input, IASTName[] refs,
|
||||||
Map<IMacroBinding, IASTFileLocation> macroDefinitionLocationMap,
|
Map<IMacroBinding, IASTFileLocation> macroDefinitionLocationMap,
|
||||||
String filePath, int lineNumber, boolean isPPCondition) {
|
String filePath, int lineNumber, boolean isPPCondition, LexerOptions options) {
|
||||||
fInput= input;
|
fInput= input;
|
||||||
fDictionary= createDictionary(refs);
|
fDictionary= createDictionary(refs);
|
||||||
fMacroLocationMap= macroDefinitionLocationMap;
|
fMacroLocationMap= macroDefinitionLocationMap;
|
||||||
fFilePath= filePath;
|
fFilePath= filePath;
|
||||||
fLineNumber= lineNumber;
|
fLineNumber= lineNumber;
|
||||||
fIsPPCondition= isPPCondition;
|
fIsPPCondition= isPPCondition;
|
||||||
|
fLexerOptions= (LexerOptions) options.clone();
|
||||||
|
fLexerOptions.fCreateImageLocations= false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CharArrayMap<PreprocessorMacro> createDictionary(IASTName[] refs) {
|
private CharArrayMap<PreprocessorMacro> createDictionary(IASTName[] refs) {
|
||||||
|
@ -80,7 +77,7 @@ public class SingleMacroExpansionExplorer extends MacroExpansionExplorer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void computeExpansion() {
|
private void computeExpansion() {
|
||||||
MacroExpander expander= new MacroExpander(ILexerLog.NULL, fDictionary, null, LEX_OPTIONS);
|
MacroExpander expander= new MacroExpander(ILexerLog.NULL, fDictionary, null, fLexerOptions);
|
||||||
MacroExpansionTracker tracker= new MacroExpansionTracker(Integer.MAX_VALUE);
|
MacroExpansionTracker tracker= new MacroExpansionTracker(Integer.MAX_VALUE);
|
||||||
expander.expand(fInput, tracker, fFilePath, fLineNumber, fIsPPCondition);
|
expander.expand(fInput, tracker, fFilePath, fLineNumber, fIsPPCondition);
|
||||||
|
|
||||||
|
@ -96,7 +93,7 @@ public class SingleMacroExpansionExplorer extends MacroExpansionExplorer {
|
||||||
if (step < 0 || step >= fExpansionCount) {
|
if (step < 0 || step >= fExpansionCount) {
|
||||||
throw new IndexOutOfBoundsException();
|
throw new IndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
MacroExpander expander= new MacroExpander(ILexerLog.NULL, fDictionary, null, LEX_OPTIONS);
|
MacroExpander expander= new MacroExpander(ILexerLog.NULL, fDictionary, null, fLexerOptions);
|
||||||
MacroExpansionTracker tracker= new MacroExpansionTracker(step);
|
MacroExpansionTracker tracker= new MacroExpansionTracker(step);
|
||||||
expander.expand(fInput, tracker, fFilePath, fLineNumber, fIsPPCondition);
|
expander.expand(fInput, tracker, fFilePath, fLineNumber, fIsPPCondition);
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
|
||||||
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
|
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
|
||||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.ExpansionOverlapsBoundaryException;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTCompletionContext;
|
import org.eclipse.cdt.core.dom.ast.IASTCompletionContext;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTImageLocation;
|
import org.eclipse.cdt.core.dom.ast.IASTImageLocation;
|
||||||
|
@ -36,6 +37,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||||
import org.eclipse.cdt.core.index.IIndexBinding;
|
import org.eclipse.cdt.core.index.IIndexBinding;
|
||||||
|
import org.eclipse.cdt.core.parser.IToken;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
|
||||||
public class PDOMASTAdapter {
|
public class PDOMASTAdapter {
|
||||||
|
@ -171,6 +173,16 @@ public class PDOMASTAdapter {
|
||||||
public IASTName getLastName() {
|
public IASTName getLastName() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IToken getLeadingSyntax() throws ExpansionOverlapsBoundaryException,
|
||||||
|
UnsupportedOperationException {
|
||||||
|
return fDelegate.getLeadingSyntax();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IToken getTrailingSyntax() throws ExpansionOverlapsBoundaryException,
|
||||||
|
UnsupportedOperationException {
|
||||||
|
return fDelegate.getTrailingSyntax();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class AnonymousEnumeration implements IEnumeration {
|
private static class AnonymousEnumeration implements IEnumeration {
|
||||||
|
|
Loading…
Add table
Reference in a new issue