mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Engine for exploring macro expansions step by step, bug 23540.
This commit is contained in:
parent
3c2dd52cf7
commit
1c83f17a74
27 changed files with 1517 additions and 214 deletions
|
@ -0,0 +1,213 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* 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.parser.tests.scanner;
|
||||||
|
|
||||||
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.parser.c.GCCScannerExtensionConfiguration;
|
||||||
|
import org.eclipse.cdt.core.parser.CodeReader;
|
||||||
|
import org.eclipse.cdt.core.parser.IToken;
|
||||||
|
import org.eclipse.cdt.core.parser.NullLogService;
|
||||||
|
import org.eclipse.cdt.core.parser.OffsetLimitReachedException;
|
||||||
|
import org.eclipse.cdt.core.parser.ParserLanguage;
|
||||||
|
import org.eclipse.cdt.core.parser.ScannerInfo;
|
||||||
|
import org.eclipse.cdt.core.testplugin.CTestPlugin;
|
||||||
|
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
|
||||||
|
import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.NullCodeReaderFactory;
|
||||||
|
import org.eclipse.cdt.internal.core.parser.scanner.CPreprocessor;
|
||||||
|
import org.eclipse.cdt.internal.core.parser.scanner.MacroExpander;
|
||||||
|
import org.eclipse.cdt.internal.core.parser.scanner.MacroExpansionTracker;
|
||||||
|
import org.eclipse.text.edits.ReplaceEdit;
|
||||||
|
|
||||||
|
|
||||||
|
public class ExpansionExplorerTests extends BaseTestCase {
|
||||||
|
|
||||||
|
public static TestSuite suite() {
|
||||||
|
return suite(ExpansionExplorerTests.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void performTest(int steps) throws Exception {
|
||||||
|
StringBuffer[] bufs= TestSourceReader.getContentsForTest(
|
||||||
|
CTestPlugin.getDefault().getBundle(), "parser", getClass(), getName(), steps+2);
|
||||||
|
String[] input= new String[steps+2];
|
||||||
|
int i= -1;
|
||||||
|
for (StringBuffer buf : bufs) {
|
||||||
|
input[++i]= buf.toString().trim();
|
||||||
|
}
|
||||||
|
final MacroExpander expander= createExpander(input[0]);
|
||||||
|
final String original= input[1];
|
||||||
|
|
||||||
|
verifyStep(expander, original, Integer.MAX_VALUE, original, input[steps+1]);
|
||||||
|
for (i= 0; i < steps; i++) {
|
||||||
|
verifyStep(expander, original, i, input[i+1], input[i+2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyStep(MacroExpander expander, String original, int step, String expectedPre,
|
||||||
|
String expectedPost) {
|
||||||
|
MacroExpansionTracker tracker= new MacroExpansionTracker(step);
|
||||||
|
expander.expand(original, tracker);
|
||||||
|
String pre = tracker.getCodeBeforeStep();
|
||||||
|
ReplaceEdit replacement = tracker.getReplacement();
|
||||||
|
assertNotNull(pre);
|
||||||
|
assertNotNull(replacement);
|
||||||
|
String post= apply(pre, replacement);
|
||||||
|
|
||||||
|
assertEquals(expectedPre, pre);
|
||||||
|
assertEquals(expectedPost, post);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String apply(String pre, ReplaceEdit replacement) {
|
||||||
|
StringBuilder buf= new StringBuilder();
|
||||||
|
buf.append(pre, 0, replacement.getOffset());
|
||||||
|
buf.append(replacement.getText());
|
||||||
|
buf.append(pre, replacement.getExclusiveEnd(), pre.length());
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private MacroExpander createExpander(final String macrodefs) throws OffsetLimitReachedException {
|
||||||
|
CPreprocessor cpp= new CPreprocessor(new CodeReader(macrodefs.toCharArray()),
|
||||||
|
new ScannerInfo(), ParserLanguage.C, new NullLogService(),
|
||||||
|
new GCCScannerExtensionConfiguration(), NullCodeReaderFactory.getInstance());
|
||||||
|
int type;
|
||||||
|
do {
|
||||||
|
type= cpp.nextTokenRaw().getType();
|
||||||
|
} while (type != IToken.tEND_OF_INPUT);
|
||||||
|
return (MacroExpander) cpp.getAdapter(MacroExpander.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #define A
|
||||||
|
|
||||||
|
// B
|
||||||
|
|
||||||
|
// B
|
||||||
|
public void testNoOp() throws Exception {
|
||||||
|
performTest(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #define A B
|
||||||
|
|
||||||
|
// A
|
||||||
|
|
||||||
|
// B
|
||||||
|
public void testObject() throws Exception {
|
||||||
|
performTest(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #define A A1
|
||||||
|
// #define A1 A2
|
||||||
|
// #define A2 A
|
||||||
|
|
||||||
|
// A
|
||||||
|
|
||||||
|
// A1
|
||||||
|
|
||||||
|
// A2
|
||||||
|
|
||||||
|
// A
|
||||||
|
public void testObjectChain() throws Exception {
|
||||||
|
performTest(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #define A(x) B+x
|
||||||
|
|
||||||
|
// A(c)
|
||||||
|
|
||||||
|
// B+c
|
||||||
|
public void testFunction() throws Exception {
|
||||||
|
performTest(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #define A(x) x+x
|
||||||
|
// #define _t t
|
||||||
|
|
||||||
|
// A(_t)
|
||||||
|
|
||||||
|
// A(t)
|
||||||
|
|
||||||
|
// t+t
|
||||||
|
public void testFunctionParam() throws Exception {
|
||||||
|
performTest(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #define A(x,y) x+y
|
||||||
|
// #define _t t
|
||||||
|
|
||||||
|
// A(_t, _t)
|
||||||
|
|
||||||
|
// A(t, _t)
|
||||||
|
|
||||||
|
// A(t, t)
|
||||||
|
|
||||||
|
// t+t
|
||||||
|
public void test2Params() throws Exception {
|
||||||
|
performTest(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #define A(x,y,z) x + y + z
|
||||||
|
// #define _t t
|
||||||
|
|
||||||
|
// A ( _t , , _t )
|
||||||
|
|
||||||
|
// A ( t , , _t )
|
||||||
|
|
||||||
|
// A ( t , , t )
|
||||||
|
|
||||||
|
// t + + t
|
||||||
|
public void test3Params() throws Exception {
|
||||||
|
performTest(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #define m !(m)+n
|
||||||
|
// #define n(n) n(m)
|
||||||
|
|
||||||
|
// m(m)
|
||||||
|
|
||||||
|
// !(m)+n(m)
|
||||||
|
|
||||||
|
// !(m)+n(!(m)+n)
|
||||||
|
|
||||||
|
// !(m)+!(m)+n(m)
|
||||||
|
|
||||||
|
// !(m)+!(m)+n(!(m)+n)
|
||||||
|
public void testRecursiveExpansion() throws Exception {
|
||||||
|
performTest(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #define f(x,y) (x + y)
|
||||||
|
// #define g(x,y) (x*y)
|
||||||
|
// #define _a a
|
||||||
|
// #define _b b
|
||||||
|
|
||||||
|
// f( g(_a,_b), g(_b,_a) )
|
||||||
|
|
||||||
|
// f( g(a,_b), g(_b,_a) )
|
||||||
|
|
||||||
|
// f( g(a,b), g(_b,_a) )
|
||||||
|
|
||||||
|
// f( (a*b), g(_b,_a) )
|
||||||
|
|
||||||
|
// f( (a*b), g(b,_a) )
|
||||||
|
|
||||||
|
// f( (a*b), g(b,a) )
|
||||||
|
|
||||||
|
// f( (a*b), (b*a) )
|
||||||
|
|
||||||
|
// ((a*b) + (b*a))
|
||||||
|
public void testNestedFunctions() throws Exception {
|
||||||
|
performTest(7);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2007 Wind River Systems, Inc. and others.
|
* Copyright (c) 2007, 2008 Wind River Systems, Inc. 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
|
||||||
|
@ -464,17 +464,18 @@ public class LocationMapTests extends BaseTestCase {
|
||||||
fLocationMap.encounteredComment(12, 23, false);
|
fLocationMap.encounteredComment(12, 23, false);
|
||||||
checkComment(fLocationMap.getComments()[0], new String(LONGDIGITS, 110, 15), false, FN, 110, 15, 2, 2);
|
checkComment(fLocationMap.getComments()[0], new String(LONGDIGITS, 110, 15), false, FN, 110, 15, 2, 2);
|
||||||
|
|
||||||
IASTName[] refs= fLocationMap.getReferences(macro1);
|
IASTName[] refs= fLocationMap.getReferences(macro3);
|
||||||
assertEquals(1, refs.length);
|
assertEquals(1, refs.length);
|
||||||
checkName(refs[0], macro1, "n1", fTu, IASTTranslationUnit.EXPANSION_NAME, ROLE_REFERENCE, FN, 110, 15, 2, 2, new String(LONGDIGITS, 110, 15));
|
IASTName macro3ref= refs[0];
|
||||||
|
checkName(refs[0], macro3, "n3", fTu, IASTTranslationUnit.EXPANSION_NAME, ROLE_REFERENCE, FN, 110, 5, 2, 2, new String(LONGDIGITS, 110, 5));
|
||||||
|
|
||||||
|
refs= fLocationMap.getReferences(macro1);
|
||||||
|
assertEquals(1, refs.length);
|
||||||
|
checkName(refs[0], macro1, "n1", macro3ref, IASTTranslationUnit.EXPANSION_NAME, ROLE_REFERENCE, FN, 110, 15, 2, 2, new String(LONGDIGITS, 110, 15));
|
||||||
|
|
||||||
refs= fLocationMap.getReferences(macro2);
|
refs= fLocationMap.getReferences(macro2);
|
||||||
assertEquals(1, refs.length);
|
assertEquals(1, refs.length);
|
||||||
checkName(refs[0], macro2, "n2", fTu, IASTTranslationUnit.EXPANSION_NAME, ROLE_REFERENCE, FN, 110, 15, 2, 2, new String(LONGDIGITS, 110, 15));
|
checkName(refs[0], macro2, "n2", macro3ref, IASTTranslationUnit.EXPANSION_NAME, ROLE_REFERENCE, FN, 110, 15, 2, 2, new String(LONGDIGITS, 110, 15));
|
||||||
|
|
||||||
refs= fLocationMap.getReferences(macro3);
|
|
||||||
assertEquals(1, refs.length);
|
|
||||||
checkName(refs[0], macro3, "n3", fTu, IASTTranslationUnit.EXPANSION_NAME, ROLE_REFERENCE, FN, 110, 5, 2, 2, new String(LONGDIGITS, 110, 5));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testContexts() {
|
public void testContexts() {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2004, 2007 IBM Corporation and others.
|
* Copyright (c) 2004, 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
|
||||||
|
@ -11,9 +11,6 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.core.parser.tests.scanner;
|
package org.eclipse.cdt.core.parser.tests.scanner;
|
||||||
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import junit.framework.TestSuite;
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.parser.IProblem;
|
import org.eclipse.cdt.core.parser.IProblem;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2004, 2007 IBM Corporation and others.
|
* Copyright (c) 2004, 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
|
||||||
|
@ -286,6 +286,69 @@ public class PreprocessorTests extends PreprocessorTestsBase {
|
||||||
validateProblemCount(0);
|
validateProblemCount(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #define variadic(x...) (a, ##x)
|
||||||
|
// #define _c c
|
||||||
|
// variadic();
|
||||||
|
// variadic(_c);
|
||||||
|
// variadic(_c,_c);
|
||||||
|
public void testGccVariadicMacroExtensions2() throws Exception {
|
||||||
|
initializeScanner();
|
||||||
|
validateToken(IToken.tLPAREN);
|
||||||
|
validateIdentifier("a");
|
||||||
|
validateToken(IToken.tRPAREN);
|
||||||
|
validateToken(IToken.tSEMI);
|
||||||
|
|
||||||
|
validateToken(IToken.tLPAREN);
|
||||||
|
validateIdentifier("a");
|
||||||
|
validateToken(IToken.tCOMMA);
|
||||||
|
validateIdentifier("c");
|
||||||
|
validateToken(IToken.tRPAREN);
|
||||||
|
validateToken(IToken.tSEMI);
|
||||||
|
|
||||||
|
validateToken(IToken.tLPAREN);
|
||||||
|
validateIdentifier("a");
|
||||||
|
validateToken(IToken.tCOMMA);
|
||||||
|
validateIdentifier("c");
|
||||||
|
validateToken(IToken.tCOMMA);
|
||||||
|
validateIdentifier("c");
|
||||||
|
validateToken(IToken.tRPAREN);
|
||||||
|
validateToken(IToken.tSEMI);
|
||||||
|
validateEOF();
|
||||||
|
validateProblemCount(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #define variadic(y, x...) (a, ##x)
|
||||||
|
// #define _c c
|
||||||
|
// variadic(1);
|
||||||
|
// variadic(,_c);
|
||||||
|
// variadic(,_c,_c);
|
||||||
|
public void testGccVariadicMacroExtensions3() throws Exception {
|
||||||
|
initializeScanner();
|
||||||
|
validateToken(IToken.tLPAREN);
|
||||||
|
validateIdentifier("a");
|
||||||
|
validateToken(IToken.tRPAREN);
|
||||||
|
validateToken(IToken.tSEMI);
|
||||||
|
|
||||||
|
validateToken(IToken.tLPAREN);
|
||||||
|
validateIdentifier("a");
|
||||||
|
validateToken(IToken.tCOMMA);
|
||||||
|
validateIdentifier("c");
|
||||||
|
validateToken(IToken.tRPAREN);
|
||||||
|
validateToken(IToken.tSEMI);
|
||||||
|
|
||||||
|
validateToken(IToken.tLPAREN);
|
||||||
|
validateIdentifier("a");
|
||||||
|
validateToken(IToken.tCOMMA);
|
||||||
|
validateIdentifier("c");
|
||||||
|
validateToken(IToken.tCOMMA);
|
||||||
|
validateIdentifier("c");
|
||||||
|
validateToken(IToken.tRPAREN);
|
||||||
|
validateToken(IToken.tSEMI);
|
||||||
|
|
||||||
|
validateEOF();
|
||||||
|
validateProblemCount(0);
|
||||||
|
}
|
||||||
|
|
||||||
// #define str(x) #x
|
// #define str(x) #x
|
||||||
// str();
|
// str();
|
||||||
public void testEmptyStringify() throws Exception {
|
public void testEmptyStringify() throws Exception {
|
||||||
|
@ -810,14 +873,14 @@ public class PreprocessorTests extends PreprocessorTestsBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void _testSpecExample3_2() throws Exception {
|
public void testSpecExample3_2() throws Exception {
|
||||||
StringBuffer sb = getExample3Defines();
|
StringBuffer sb = getExample3Defines();
|
||||||
sb.append("g(x+(3,4)-w) | h 5) & m (f)^m(m); \n");
|
sb.append("g(x+(3,4)-w) | h 5) & m (f)^m(m); \n");
|
||||||
|
|
||||||
// f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1); //47
|
// f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1); //47
|
||||||
initializeScanner(sb.toString());
|
initializeScanner(sb.toString());
|
||||||
|
|
||||||
validateIdentifier("g");
|
validateIdentifier("f");
|
||||||
validateToken(IToken.tLPAREN);
|
validateToken(IToken.tLPAREN);
|
||||||
validateInteger("2");
|
validateInteger("2");
|
||||||
validateToken(IToken.tSTAR);
|
validateToken(IToken.tSTAR);
|
||||||
|
@ -849,7 +912,7 @@ public class PreprocessorTests extends PreprocessorTestsBase {
|
||||||
validateIdentifier("f");
|
validateIdentifier("f");
|
||||||
validateToken(IToken.tLPAREN);
|
validateToken(IToken.tLPAREN);
|
||||||
validateInteger("2");
|
validateInteger("2");
|
||||||
validateToken(IToken.tLPAREN);
|
validateToken(IToken.tSTAR);
|
||||||
validateToken(IToken.tLPAREN);
|
validateToken(IToken.tLPAREN);
|
||||||
validateInteger("0");
|
validateInteger("0");
|
||||||
validateToken(IToken.tCOMMA);
|
validateToken(IToken.tCOMMA);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2007 Wind River Systems, Inc. and others.
|
* Copyright (c) 2007, 2008 Wind River Systems, Inc. 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
|
||||||
|
@ -23,6 +23,7 @@ public class ScannerTestSuite extends TestSuite {
|
||||||
suite.addTest(PreprocessorTests.suite());
|
suite.addTest(PreprocessorTests.suite());
|
||||||
suite.addTest(InclusionTests.suite());
|
suite.addTest(InclusionTests.suite());
|
||||||
suite.addTest(PreprocessorBugsTests.suite());
|
suite.addTest(PreprocessorBugsTests.suite());
|
||||||
|
suite.addTest(ExpansionExplorerTests.suite());
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
* Copyright (c) 2005, 2006 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 - Initial API and implementation
|
|
||||||
* Markus Schorn (Wind River Systems)
|
|
||||||
*******************************************************************************/
|
|
||||||
package org.eclipse.cdt.core.dom;
|
|
||||||
|
|
||||||
import org.eclipse.core.runtime.IAdaptable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated use IIndex instead.
|
|
||||||
*/
|
|
||||||
public interface IPDOM extends IAdaptable {}
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2004, 2007 IBM Corporation and others.
|
* Copyright (c) 2004, 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
|
||||||
|
@ -27,6 +27,12 @@ public interface IASTMacroExpansion extends IASTNodeLocation {
|
||||||
*/
|
*/
|
||||||
public IASTPreprocessorMacroDefinition getMacroDefinition();
|
public IASTPreprocessorMacroDefinition getMacroDefinition();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The macro reference for the explicit macro expansion containing this expansion.
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public IASTName getMacroReference();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an offset within the macro-expansion. The offset can be used to compare
|
* Returns an offset within the macro-expansion. The offset can be used to compare
|
||||||
* nodes within the same macro-expansion. However, it does not serve as an offset
|
* nodes within the same macro-expansion. However, it does not serve as an offset
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2004, 2007 IBM Corporation and others.
|
* Copyright (c) 2004, 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
|
||||||
|
@ -117,16 +117,7 @@ public interface IASTTranslationUnit extends IASTNode, IAdaptable {
|
||||||
public IASTName[] getReferences(IBinding binding);
|
public IASTName[] getReferences(IBinding binding);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of locations. This is a sequence of file locations and macro-expansion locations.
|
* Select the node in the treat that best fits the offset/length/file path.
|
||||||
* @param offset sequence number as stored in the ast nodes.
|
|
||||||
* @param length
|
|
||||||
* @return and array of locations.
|
|
||||||
* @deprecated the offsets needed for this method are not accessible via public API.
|
|
||||||
*/
|
|
||||||
public IASTNodeLocation[] getLocationInfo(int offset, int length);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Select the node in the treet that best fits the offset/length/file path.
|
|
||||||
*
|
*
|
||||||
* @param path - file name specified through path
|
* @param path - file name specified through path
|
||||||
* @param offset - location in the file as an offset
|
* @param offset - location in the file as an offset
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* 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.rewrite;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
|
||||||
|
import org.eclipse.cdt.internal.core.parser.scanner.MultiMacroExpansionExplorer;
|
||||||
|
import org.eclipse.jface.text.IRegion;
|
||||||
|
import org.eclipse.text.edits.ReplaceEdit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to understand macro expansions step by step.
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public abstract class MacroExpansionExplorer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representation of a single expansion step or a complete expansion.
|
||||||
|
*/
|
||||||
|
public interface IMacroExpansionStep {
|
||||||
|
/**
|
||||||
|
* Returns the code before this step.
|
||||||
|
*/
|
||||||
|
String getCodeBeforeStep();
|
||||||
|
/**
|
||||||
|
* Returns the code after this step.
|
||||||
|
*/
|
||||||
|
String getCodeAfterStep();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of replacements representing the change from the code before
|
||||||
|
* this step to the code after this step.
|
||||||
|
*/
|
||||||
|
ReplaceEdit[] getReplacements();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the macro that gets expanded in this step, or <code>null</code> for
|
||||||
|
* a step representing a full expansion.
|
||||||
|
*/
|
||||||
|
IMacroBinding getExpandedMacro();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a macro expansion explorer for a given file location in a translation unit.
|
||||||
|
*/
|
||||||
|
public static MacroExpansionExplorer create(IASTTranslationUnit tu, IASTFileLocation loc) {
|
||||||
|
return new MultiMacroExpansionExplorer(tu, loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a macro expansion explorer for a given region in the outermost file of a
|
||||||
|
* translation unit.
|
||||||
|
*/
|
||||||
|
public static MacroExpansionExplorer create(IASTTranslationUnit tu, IRegion loc) {
|
||||||
|
return new MultiMacroExpansionExplorer(tu, loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the full expansion for the region of this expansion explorer.
|
||||||
|
*/
|
||||||
|
public abstract IMacroExpansionStep getFullExpansion();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the total number of available steps for expanding the region of this expansion
|
||||||
|
* explorer.
|
||||||
|
*/
|
||||||
|
public abstract int getExpansionStepCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a description for the requested step within the expansion of the region of this
|
||||||
|
* expansion explorer.
|
||||||
|
* @throws IndexOutOfBoundsException if step < 0 or step >= getExpansionStepCount().
|
||||||
|
*/
|
||||||
|
public abstract IMacroExpansionStep getExpansionStep(int step) throws IndexOutOfBoundsException;
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2007 IBM Corporation and others.
|
* Copyright (c) 2007, 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
|
||||||
|
@ -10,9 +10,11 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.core.parser.util;
|
package org.eclipse.cdt.core.parser.util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -174,6 +176,15 @@ public final class CharArrayMap<V> implements ICharArrayMap<V> {
|
||||||
return map.values();
|
return map.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<char[]> keys() {
|
||||||
|
Set<Key> keys= map.keySet();
|
||||||
|
ArrayList<char[]> r= new ArrayList<char[]>(keys.size());
|
||||||
|
for (Key key : keys) {
|
||||||
|
r.add(CharArrayUtils.extract(key.buffer, key.start, key.length));
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
map.clear();
|
map.clear();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2002, 2007 IBM Corporation and others.
|
* Copyright (c) 2002, 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
|
||||||
|
@ -57,7 +57,6 @@ import org.eclipse.core.runtime.CoreException;
|
||||||
public class CASTTranslationUnit extends CASTNode implements IASTTranslationUnit {
|
public class CASTTranslationUnit extends CASTNode implements IASTTranslationUnit {
|
||||||
|
|
||||||
private static final IASTPreprocessorStatement[] EMPTY_PREPROCESSOR_STATEMENT_ARRAY = new IASTPreprocessorStatement[0];
|
private static final IASTPreprocessorStatement[] EMPTY_PREPROCESSOR_STATEMENT_ARRAY = new IASTPreprocessorStatement[0];
|
||||||
private static final IASTNodeLocation[] EMPTY_PREPROCESSOR_LOCATION_ARRAY = new IASTNodeLocation[0];
|
|
||||||
private static final IASTPreprocessorMacroDefinition[] EMPTY_PREPROCESSOR_MACRODEF_ARRAY = new IASTPreprocessorMacroDefinition[0];
|
private static final IASTPreprocessorMacroDefinition[] EMPTY_PREPROCESSOR_MACRODEF_ARRAY = new IASTPreprocessorMacroDefinition[0];
|
||||||
private static final IASTPreprocessorIncludeStatement[] EMPTY_PREPROCESSOR_INCLUSION_ARRAY = new IASTPreprocessorIncludeStatement[0];
|
private static final IASTPreprocessorIncludeStatement[] EMPTY_PREPROCESSOR_INCLUSION_ARRAY = new IASTPreprocessorIncludeStatement[0];
|
||||||
private static final IASTProblem[] EMPTY_PROBLEM_ARRAY = new IASTProblem[0];
|
private static final IASTProblem[] EMPTY_PROBLEM_ARRAY = new IASTProblem[0];
|
||||||
|
@ -185,18 +184,6 @@ public class CASTTranslationUnit extends CASTNode implements IASTTranslationUnit
|
||||||
return CVisitor.getReferences(this, binding);
|
return CVisitor.getReferences(this, binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see org.eclipse.cdt.core.dom.ast.IASTTranslationUnit#getLocationInfo(int,
|
|
||||||
* int)
|
|
||||||
*/
|
|
||||||
public IASTNodeLocation[] getLocationInfo(int offset, int length) {
|
|
||||||
if (resolver == null)
|
|
||||||
return EMPTY_PREPROCESSOR_LOCATION_ARRAY;
|
|
||||||
return resolver.getLocations(offset, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class CFindNodeForOffsetAction extends CASTVisitor {
|
private class CFindNodeForOffsetAction extends CASTVisitor {
|
||||||
{
|
{
|
||||||
shouldVisitNames = true;
|
shouldVisitNames = true;
|
||||||
|
@ -546,6 +533,7 @@ public class CASTTranslationUnit extends CASTNode implements IASTTranslationUnit
|
||||||
return new IASTComment[0];
|
return new IASTComment[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public Object getAdapter(Class adapter) {
|
public Object getAdapter(Class adapter) {
|
||||||
if (adapter.isAssignableFrom(resolver.getClass())) {
|
if (adapter.isAssignableFrom(resolver.getClass())) {
|
||||||
return resolver;
|
return resolver;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2004, 2007 IBM Corporation and others.
|
* Copyright (c) 2004, 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
|
||||||
|
@ -71,7 +71,6 @@ import org.eclipse.core.runtime.CoreException;
|
||||||
public class CPPASTTranslationUnit extends CPPASTNode implements ICPPASTTranslationUnit, IASTAmbiguityParent {
|
public class CPPASTTranslationUnit extends CPPASTNode implements ICPPASTTranslationUnit, IASTAmbiguityParent {
|
||||||
|
|
||||||
private static final IASTPreprocessorStatement[] EMPTY_PREPROCESSOR_STATEMENT_ARRAY = new IASTPreprocessorStatement[0];
|
private static final IASTPreprocessorStatement[] EMPTY_PREPROCESSOR_STATEMENT_ARRAY = new IASTPreprocessorStatement[0];
|
||||||
private static final IASTNodeLocation[] EMPTY_PREPROCESSOR_LOCATION_ARRAY = new IASTNodeLocation[0];
|
|
||||||
private static final IASTPreprocessorMacroDefinition[] EMPTY_PREPROCESSOR_MACRODEF_ARRAY = new IASTPreprocessorMacroDefinition[0];
|
private static final IASTPreprocessorMacroDefinition[] EMPTY_PREPROCESSOR_MACRODEF_ARRAY = new IASTPreprocessorMacroDefinition[0];
|
||||||
private static final IASTPreprocessorIncludeStatement[] EMPTY_PREPROCESSOR_INCLUSION_ARRAY = new IASTPreprocessorIncludeStatement[0];
|
private static final IASTPreprocessorIncludeStatement[] EMPTY_PREPROCESSOR_INCLUSION_ARRAY = new IASTPreprocessorIncludeStatement[0];
|
||||||
private static final String EMPTY_STRING = ""; //$NON-NLS-1$
|
private static final String EMPTY_STRING = ""; //$NON-NLS-1$
|
||||||
|
@ -225,13 +224,6 @@ public class CPPASTTranslationUnit extends CPPASTNode implements ICPPASTTranslat
|
||||||
return CPPVisitor.getReferences(this, b);
|
return CPPVisitor.getReferences(this, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public IASTNodeLocation[] getLocationInfo(int offset, int length) {
|
|
||||||
if (resolver == null)
|
|
||||||
return EMPTY_PREPROCESSOR_LOCATION_ARRAY;
|
|
||||||
return resolver.getLocations(offset, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class CPPFindNodeForOffsetAction extends CPPASTVisitor {
|
private class CPPFindNodeForOffsetAction extends CPPASTVisitor {
|
||||||
{
|
{
|
||||||
shouldVisitNames = true;
|
shouldVisitNames = true;
|
||||||
|
@ -512,6 +504,7 @@ public class CPPASTTranslationUnit extends CPPASTNode implements ICPPASTTranslat
|
||||||
return new IASTComment[0];
|
return new IASTComment[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public Object getAdapter(Class adapter) {
|
public Object getAdapter(Class adapter) {
|
||||||
if (adapter.isAssignableFrom(resolver.getClass())) {
|
if (adapter.isAssignableFrom(resolver.getClass())) {
|
||||||
return resolver;
|
return resolver;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2007 Wind River Systems, Inc. and others.
|
* Copyright (c) 2007, 2008 Wind River Systems, Inc. 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
|
||||||
|
@ -124,10 +124,12 @@ class ASTMacroReferenceName extends ASTPreprocessorName {
|
||||||
fImageLocationInfo= imgLocationInfo;
|
fImageLocationInfo= imgLocationInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isReference() {
|
public boolean isReference() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public IASTImageLocation getImageLocation() {
|
public IASTImageLocation getImageLocation() {
|
||||||
if (fImageLocationInfo != null) {
|
if (fImageLocationInfo != null) {
|
||||||
IASTTranslationUnit tu= getTranslationUnit();
|
IASTTranslationUnit tu= getTranslationUnit();
|
||||||
|
|
|
@ -467,6 +467,10 @@ class ASTFileLocation implements IASTFileLocation {
|
||||||
public int getSequenceEndNumber() {
|
public int getSequenceEndNumber() {
|
||||||
return fLocationCtx.getSequenceNumberForOffset(fOffset+fLength, true);
|
return fLocationCtx.getSequenceNumberForOffset(fOffset+fLength, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LocationCtxFile getLocationContext() {
|
||||||
|
return fLocationCtx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ASTMacroExpansionLocation implements IASTMacroExpansion {
|
class ASTMacroExpansionLocation implements IASTMacroExpansion {
|
||||||
|
@ -490,6 +494,10 @@ class ASTMacroExpansionLocation implements IASTMacroExpansion {
|
||||||
return fContext.getMacroDefinition();
|
return fContext.getMacroDefinition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IASTName getMacroReference() {
|
||||||
|
return fContext.getMacroReference();
|
||||||
|
}
|
||||||
|
|
||||||
public IASTFileLocation asFileLocation() {
|
public IASTFileLocation asFileLocation() {
|
||||||
return ((LocationCtxContainer) fContext.getParent()).createFileLocation(fContext.fOffsetInParent, fContext.fEndOffsetInParent-fContext.fOffsetInParent);
|
return ((LocationCtxContainer) fContext.getParent()).createFileLocation(fContext.fOffsetInParent, fContext.fEndOffsetInParent-fContext.fOffsetInParent);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,9 @@ package org.eclipse.cdt.internal.core.parser.scanner;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.text.DateFormatSymbols;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -42,18 +44,19 @@ import org.eclipse.cdt.core.parser.OffsetLimitReachedException;
|
||||||
import org.eclipse.cdt.core.parser.ParseError;
|
import org.eclipse.cdt.core.parser.ParseError;
|
||||||
import org.eclipse.cdt.core.parser.ParserLanguage;
|
import org.eclipse.cdt.core.parser.ParserLanguage;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayIntMap;
|
import org.eclipse.cdt.core.parser.util.CharArrayIntMap;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
|
import org.eclipse.cdt.core.parser.util.CharArrayMap;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator.EvalException;
|
import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator.EvalException;
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
|
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner.MacroDefinitionParser.InvalidMacroDefinitionException;
|
import org.eclipse.cdt.internal.core.parser.scanner.MacroDefinitionParser.InvalidMacroDefinitionException;
|
||||||
|
import org.eclipse.core.runtime.IAdaptable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C-Preprocessor providing tokens for the parsers. The class should not be used directly, rather than that
|
* C-Preprocessor providing tokens for the parsers. The class should not be used directly, rather than that
|
||||||
* you should be using the {@link IScanner} interface.
|
* you should be using the {@link IScanner} interface.
|
||||||
* @since 5.0
|
* @since 5.0
|
||||||
*/
|
*/
|
||||||
public class CPreprocessor implements ILexerLog, IScanner {
|
public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
||||||
public static final String PROP_VALUE = "CPreprocessor"; //$NON-NLS-1$
|
public static final String PROP_VALUE = "CPreprocessor"; //$NON-NLS-1$
|
||||||
|
|
||||||
public static final int tDEFINED= IToken.FIRST_RESERVED_PREPROCESSOR;
|
public static final int tDEFINED= IToken.FIRST_RESERVED_PREPROCESSOR;
|
||||||
|
@ -62,7 +65,6 @@ public class CPreprocessor implements ILexerLog, IScanner {
|
||||||
public static final int tSPACE= IToken.FIRST_RESERVED_PREPROCESSOR+3;
|
public static final int tSPACE= IToken.FIRST_RESERVED_PREPROCESSOR+3;
|
||||||
public static final int tNOSPACE= IToken.FIRST_RESERVED_PREPROCESSOR+4;
|
public static final int tNOSPACE= IToken.FIRST_RESERVED_PREPROCESSOR+4;
|
||||||
public static final int tMACRO_PARAMETER= IToken.FIRST_RESERVED_PREPROCESSOR+5;
|
public static final int tMACRO_PARAMETER= IToken.FIRST_RESERVED_PREPROCESSOR+5;
|
||||||
public static final int tEMPTY_TOKEN = IToken.FIRST_RESERVED_PREPROCESSOR+6;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -81,6 +83,7 @@ public class CPreprocessor implements ILexerLog, IScanner {
|
||||||
private static final ObjectStyleMacro __STDC_HOSTED__ = new ObjectStyleMacro("__STDC_HOSTED_".toCharArray(), ONE); //$NON-NLS-1$
|
private static final ObjectStyleMacro __STDC_HOSTED__ = new ObjectStyleMacro("__STDC_HOSTED_".toCharArray(), ONE); //$NON-NLS-1$
|
||||||
private static final ObjectStyleMacro __STDC_VERSION__ = new ObjectStyleMacro("__STDC_VERSION_".toCharArray(), "199901L".toCharArray()); //$NON-NLS-1$ //$NON-NLS-2$
|
private static final ObjectStyleMacro __STDC_VERSION__ = new ObjectStyleMacro("__STDC_VERSION_".toCharArray(), "199901L".toCharArray()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
|
||||||
|
|
||||||
private interface IIncludeFileTester {
|
private interface IIncludeFileTester {
|
||||||
Object checkFile(String path, String fileName);
|
Object checkFile(String path, String fileName);
|
||||||
}
|
}
|
||||||
|
@ -120,7 +123,8 @@ public class CPreprocessor implements ILexerLog, IScanner {
|
||||||
public Token execute() {
|
public Token execute() {
|
||||||
StringBuffer buffer = new StringBuffer("\""); //$NON-NLS-1$
|
StringBuffer buffer = new StringBuffer("\""); //$NON-NLS-1$
|
||||||
Calendar cal = Calendar.getInstance();
|
Calendar cal = Calendar.getInstance();
|
||||||
buffer.append(cal.get(Calendar.MONTH));
|
DateFormatSymbols dfs= new DateFormatSymbols();
|
||||||
|
buffer.append(dfs.getShortMonths()[cal.get(Calendar.MONTH)]);
|
||||||
buffer.append(" "); //$NON-NLS-1$
|
buffer.append(" "); //$NON-NLS-1$
|
||||||
append(buffer, cal.get(Calendar.DAY_OF_MONTH));
|
append(buffer, cal.get(Calendar.DAY_OF_MONTH));
|
||||||
buffer.append(" "); //$NON-NLS-1$
|
buffer.append(" "); //$NON-NLS-1$
|
||||||
|
@ -140,7 +144,7 @@ public class CPreprocessor implements ILexerLog, IScanner {
|
||||||
public Token execute() {
|
public Token execute() {
|
||||||
StringBuffer buffer = new StringBuffer("\""); //$NON-NLS-1$
|
StringBuffer buffer = new StringBuffer("\""); //$NON-NLS-1$
|
||||||
Calendar cal = Calendar.getInstance();
|
Calendar cal = Calendar.getInstance();
|
||||||
append(buffer, cal.get(Calendar.HOUR));
|
append(buffer, cal.get(Calendar.HOUR_OF_DAY));
|
||||||
buffer.append(":"); //$NON-NLS-1$
|
buffer.append(":"); //$NON-NLS-1$
|
||||||
append(buffer, cal.get(Calendar.MINUTE));
|
append(buffer, cal.get(Calendar.MINUTE));
|
||||||
buffer.append(":"); //$NON-NLS-1$
|
buffer.append(":"); //$NON-NLS-1$
|
||||||
|
@ -176,7 +180,7 @@ public class CPreprocessor implements ILexerLog, IScanner {
|
||||||
private boolean fHandledCompletion= false;
|
private boolean fHandledCompletion= false;
|
||||||
|
|
||||||
// state information
|
// state information
|
||||||
private final CharArrayObjectMap fMacroDictionary = new CharArrayObjectMap(512);
|
private final CharArrayMap<PreprocessorMacro> fMacroDictionary = new CharArrayMap<PreprocessorMacro>(512);
|
||||||
private final LocationMap fLocationMap = new LocationMap();
|
private final LocationMap fLocationMap = new LocationMap();
|
||||||
|
|
||||||
/** Set of already included files */
|
/** Set of already included files */
|
||||||
|
@ -345,9 +349,9 @@ public class CPreprocessor implements ILexerLog, IScanner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Object[] predefined= fMacroDictionary.valueArray();
|
Collection<PreprocessorMacro> predefined= fMacroDictionary.values();
|
||||||
for (int i = 0; i < predefined.length; i++) {
|
for (PreprocessorMacro macro : predefined) {
|
||||||
fLocationMap.registerPredefinedMacro((PreprocessorMacro) predefined[i]);
|
fLocationMap.registerPredefinedMacro(macro);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,13 +417,10 @@ public class CPreprocessor implements ILexerLog, IScanner {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, IMacroBinding> getMacroDefinitions() {
|
public Map<String, IMacroBinding> getMacroDefinitions() {
|
||||||
final CharArrayObjectMap objMap= fMacroDictionary;
|
Map<String, IMacroBinding> hashMap = new HashMap<String, IMacroBinding>(fMacroDictionary.size());
|
||||||
int size = objMap.size();
|
for (char[] key : fMacroDictionary.keys()) {
|
||||||
Map<String, IMacroBinding> hashMap = new HashMap<String, IMacroBinding>(size);
|
hashMap.put(String.valueOf(key), fMacroDictionary.get(key));
|
||||||
for (int i = 0; i < size; i++) {
|
}
|
||||||
hashMap.put(String.valueOf(objMap.keyAt(i)), (IMacroBinding) objMap.getAt(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
return hashMap;
|
return hashMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1165,7 +1166,7 @@ public class CPreprocessor implements ILexerLog, IScanner {
|
||||||
lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
|
lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
|
||||||
final int endOffset= lexer.currentToken().getEndOffset();
|
final int endOffset= lexer.currentToken().getEndOffset();
|
||||||
final char[] namechars= name.getCharImage();
|
final char[] namechars= name.getCharImage();
|
||||||
PreprocessorMacro definition= (PreprocessorMacro) fMacroDictionary.remove(namechars, 0, namechars.length);
|
PreprocessorMacro definition= fMacroDictionary.remove(namechars, 0, namechars.length);
|
||||||
fLocationMap.encounterPoundUndef(definition, startOffset, name.getOffset(), name.getEndOffset(), endOffset, namechars);
|
fLocationMap.encounterPoundUndef(definition, startOffset, name.getOffset(), name.getEndOffset(), endOffset, namechars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1392,7 +1393,7 @@ public class CPreprocessor implements ILexerLog, IScanner {
|
||||||
*/
|
*/
|
||||||
private boolean expandMacro(final Token identifier, Lexer lexer, boolean stopAtNewline) throws OffsetLimitReachedException {
|
private boolean expandMacro(final Token identifier, Lexer lexer, boolean stopAtNewline) throws OffsetLimitReachedException {
|
||||||
final char[] name= identifier.getCharImage();
|
final char[] name= identifier.getCharImage();
|
||||||
PreprocessorMacro macro= (PreprocessorMacro) fMacroDictionary.get(name);
|
PreprocessorMacro macro= fMacroDictionary.get(name);
|
||||||
if (macro == null) {
|
if (macro == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1419,4 +1420,12 @@ public class CPreprocessor implements ILexerLog, IScanner {
|
||||||
fCurrentContext= new ScannerContext(ctx, fCurrentContext, replacement);
|
fCurrentContext= new ScannerContext(ctx, fCurrentContext, replacement);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Object getAdapter(Class adapter) {
|
||||||
|
if (adapter.isAssignableFrom(fMacroExpander.getClass())) {
|
||||||
|
return fMacroExpander;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2004, 2007 IBM Corporation and others.
|
* Copyright (c) 2004, 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
|
||||||
|
@ -15,7 +15,7 @@ package org.eclipse.cdt.internal.core.parser.scanner;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.parser.IProblem;
|
import org.eclipse.cdt.core.parser.IProblem;
|
||||||
import org.eclipse.cdt.core.parser.IToken;
|
import org.eclipse.cdt.core.parser.IToken;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
|
import org.eclipse.cdt.core.parser.util.CharArrayMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to evaluate expressions in preprocessor directives.
|
* Used to evaluate expressions in preprocessor directives.
|
||||||
|
@ -40,11 +40,11 @@ class ExpressionEvaluator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Token fTokens;
|
private Token fTokens;
|
||||||
private CharArrayObjectMap fDictionary;
|
private CharArrayMap<PreprocessorMacro> fDictionary;
|
||||||
|
|
||||||
public boolean evaluate(TokenList condition, CharArrayObjectMap dictionary) throws EvalException {
|
public boolean evaluate(TokenList condition, CharArrayMap<PreprocessorMacro> macroDictionary) throws EvalException {
|
||||||
fTokens= condition.first();
|
fTokens= condition.first();
|
||||||
fDictionary= dictionary;
|
fDictionary= macroDictionary;
|
||||||
return expression() != 0;
|
return expression() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2004, 2007 IBM Corporation and others.
|
* Copyright (c) 2004, 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
|
||||||
|
@ -14,6 +14,7 @@ package org.eclipse.cdt.internal.core.parser.scanner;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTComment;
|
import org.eclipse.cdt.core.dom.ast.IASTComment;
|
||||||
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.IASTMacroExpansion;
|
||||||
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;
|
||||||
|
@ -103,9 +104,12 @@ public interface ILocationResolver {
|
||||||
*/
|
*/
|
||||||
IASTFileLocation getMappedFileLocation(int offset, int length);
|
IASTFileLocation getMappedFileLocation(int offset, int length);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see IASTTranslationUnit#getLocationInfo(int, int).
|
* Returns an array of locations. This is a sequence of file locations and macro-expansion locations.
|
||||||
*/
|
* @param offset sequence number as stored in the ast nodes.
|
||||||
|
* @param length
|
||||||
|
* @return and array of locations.
|
||||||
|
*/
|
||||||
IASTNodeLocation[] getLocations(int sequenceNumber, int length);
|
IASTNodeLocation[] getLocations(int sequenceNumber, int length);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -122,7 +126,7 @@ public interface ILocationResolver {
|
||||||
int getSequenceNumberForFileOffset(String filePath, int fileOffset);
|
int getSequenceNumberForFileOffset(String filePath, int fileOffset);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see IASTTranslationUnit#getUnpreprocessedSignature(IASTFileLocation).
|
* @see IASTNode#getRawSignature().
|
||||||
*/
|
*/
|
||||||
char[] getUnpreprocessedSignature(IASTFileLocation loc);
|
char[] getUnpreprocessedSignature(IASTFileLocation loc);
|
||||||
|
|
||||||
|
@ -144,4 +148,21 @@ public interface ILocationResolver {
|
||||||
* Same as {@link #getMappedFileLocation(int, int)} for the given array of consecutive node locations.
|
* Same as {@link #getMappedFileLocation(int, int)} for the given array of consecutive node locations.
|
||||||
*/
|
*/
|
||||||
IASTFileLocation flattenLocations(IASTNodeLocation[] nodeLocations);
|
IASTFileLocation flattenLocations(IASTNodeLocation[] nodeLocations);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all explicit macro expansions that intersect with the given file location.
|
||||||
|
* Include files that may be included within the given location are not examined.
|
||||||
|
* @param loc the file-location to search for macro references
|
||||||
|
* @return an array of macro expansions.
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
IASTMacroExpansion[] getMacroExpansions(IASTFileLocation loc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all implicit macro references related to an explicit one.
|
||||||
|
* @param ref an explicit macro expansion.
|
||||||
|
* @return an array of names representing implicit macro expansions.
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
IASTName[] getImplicitMacroReferences(IASTName ref);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
|
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree.IASTInclusionNode;
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree.IASTInclusionNode;
|
||||||
|
|
||||||
|
@ -103,14 +102,14 @@ abstract class LocationCtx implements ILocationCtx {
|
||||||
* 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.
|
||||||
*/
|
*/
|
||||||
public IASTFileLocation findMappedFileLocation(int sequenceNumber, int length) {
|
public ASTFileLocation findMappedFileLocation(int sequenceNumber, int length) {
|
||||||
return fParent.createMappedFileLocation(fOffsetInParent, fEndOffsetInParent-fOffsetInParent);
|
return fParent.createMappedFileLocation(fOffsetInParent, fEndOffsetInParent-fOffsetInParent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the file location containing the specified offset range in this context.
|
* Returns the file location containing the specified offset range in this context.
|
||||||
*/
|
*/
|
||||||
public IASTFileLocation createMappedFileLocation(int offset, int length) {
|
public ASTFileLocation createMappedFileLocation(int offset, int length) {
|
||||||
return fParent.createMappedFileLocation(fOffsetInParent, fEndOffsetInParent-fOffsetInParent);
|
return fParent.createMappedFileLocation(fOffsetInParent, fEndOffsetInParent-fOffsetInParent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ class LocationCtxContainer extends LocationCtx {
|
||||||
fSource= source;
|
fSource= source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Collection<LocationCtx> getChildren() {
|
public Collection<LocationCtx> getChildren() {
|
||||||
if (fChildren == null) {
|
if (fChildren == null) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
@ -84,10 +85,12 @@ class LocationCtxContainer extends LocationCtx {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void addChildSequenceLength(int childLength) {
|
public void addChildSequenceLength(int childLength) {
|
||||||
fChildSequenceLength+= childLength;
|
fChildSequenceLength+= childLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public final LocationCtx findSurroundingContext(int sequenceNumber, int length) {
|
public final LocationCtx findSurroundingContext(int sequenceNumber, int length) {
|
||||||
int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber;
|
int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber;
|
||||||
final LocationCtx child= findChildLessOrEqualThan(sequenceNumber, false);
|
final LocationCtx child= findChildLessOrEqualThan(sequenceNumber, false);
|
||||||
|
@ -97,6 +100,7 @@ class LocationCtxContainer extends LocationCtx {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public final LocationCtxMacroExpansion findSurroundingMacroExpansion(int sequenceNumber, int length) {
|
public final LocationCtxMacroExpansion findSurroundingMacroExpansion(int sequenceNumber, int length) {
|
||||||
int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber;
|
int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber;
|
||||||
final LocationCtx child= findChildLessOrEqualThan(sequenceNumber, true);
|
final LocationCtx child= findChildLessOrEqualThan(sequenceNumber, true);
|
||||||
|
@ -106,7 +110,8 @@ class LocationCtxContainer extends LocationCtx {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IASTFileLocation findMappedFileLocation(int sequenceNumber, int length) {
|
@Override
|
||||||
|
public ASTFileLocation findMappedFileLocation(int sequenceNumber, int length) {
|
||||||
// try to delegate to a child.
|
// try to delegate to a child.
|
||||||
int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber;
|
int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber;
|
||||||
final LocationCtx child= findChildLessOrEqualThan(sequenceNumber, false);
|
final LocationCtx child= findChildLessOrEqualThan(sequenceNumber, false);
|
||||||
|
@ -198,6 +203,7 @@ class LocationCtxContainer extends LocationCtx {
|
||||||
return idx >= 0 ? fChildren.get(idx) : null;
|
return idx >= 0 ? fChildren.get(idx) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void getInclusions(ArrayList<IASTInclusionNode> result) {
|
public void getInclusions(ArrayList<IASTInclusionNode> result) {
|
||||||
if (fChildren != null) {
|
if (fChildren != null) {
|
||||||
for (Iterator<LocationCtx> iterator = fChildren.iterator(); iterator.hasNext();) {
|
for (Iterator<LocationCtx> iterator = fChildren.iterator(); iterator.hasNext();) {
|
||||||
|
@ -212,6 +218,7 @@ class LocationCtxContainer extends LocationCtx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getLineNumber(int offset) {
|
public int getLineNumber(int offset) {
|
||||||
if (fLineOffsets == null) {
|
if (fLineOffsets == null) {
|
||||||
fLineOffsets= computeLineOffsets();
|
fLineOffsets= computeLineOffsets();
|
||||||
|
|
|
@ -10,7 +10,10 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.parser.scanner;
|
package org.eclipse.cdt.internal.core.parser.scanner;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTMacroExpansion;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A location context representing a file.
|
* A location context representing a file.
|
||||||
|
@ -26,15 +29,18 @@ class LocationCtxFile extends LocationCtxContainer {
|
||||||
fASTInclude= inclusionStatement;
|
fASTInclude= inclusionStatement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public final void addChildSequenceLength(int childLength) {
|
public final void addChildSequenceLength(int childLength) {
|
||||||
super.addChildSequenceLength(childLength);
|
super.addChildSequenceLength(childLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public final String getFilePath() {
|
public final String getFilePath() {
|
||||||
return fFilename;
|
return fFilename;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IASTFileLocation findMappedFileLocation(int sequenceNumber, int length) {
|
@Override
|
||||||
|
public ASTFileLocation findMappedFileLocation(int sequenceNumber, int length) {
|
||||||
// try to delegate to a child.
|
// try to delegate to a child.
|
||||||
final int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber;
|
final int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber;
|
||||||
final int sequenceEnd= sequenceNumber+length;
|
final int sequenceEnd= sequenceNumber+length;
|
||||||
|
@ -76,14 +82,17 @@ class LocationCtxFile extends LocationCtxContainer {
|
||||||
return new ASTFileLocation(this, startOffset, endOffset-startOffset);
|
return new ASTFileLocation(this, startOffset, endOffset-startOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IASTFileLocation createMappedFileLocation(int offset, int length) {
|
@Override
|
||||||
|
public ASTFileLocation createMappedFileLocation(int offset, int length) {
|
||||||
return new ASTFileLocation(this, offset, length);
|
return new ASTFileLocation(this, offset, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public ASTInclusionStatement getInclusionStatement() {
|
public ASTInclusionStatement getInclusionStatement() {
|
||||||
return fASTInclude;
|
return fASTInclude;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
ASTFileLocation createFileLocation(int start, int length) {
|
ASTFileLocation createFileLocation(int start, int length) {
|
||||||
return new ASTFileLocation(this, start, length);
|
return new ASTFileLocation(this, start, length);
|
||||||
}
|
}
|
||||||
|
@ -95,4 +104,20 @@ class LocationCtxFile extends LocationCtxContainer {
|
||||||
}
|
}
|
||||||
return sequenceNumber >= child.fSequenceNumber + child.getSequenceLength();
|
return sequenceNumber >= child.fSequenceNumber + child.getSequenceLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void collectExplicitMacroExpansions(int offset, int length, ArrayList<IASTMacroExpansion> result) {
|
||||||
|
Collection<LocationCtx> children= getChildren();
|
||||||
|
for (LocationCtx ctx : children) {
|
||||||
|
// context must start before the end of the search range
|
||||||
|
if (ctx.fOffsetInParent >= offset+length) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ctx instanceof LocationCtxMacroExpansion) {
|
||||||
|
// expansion must end after the search start
|
||||||
|
if (ctx.fEndOffsetInParent > offset) {
|
||||||
|
result.add(new ASTMacroExpansionLocation(((LocationCtxMacroExpansion) ctx), 0, ctx.getSequenceLength()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -19,6 +19,7 @@ import java.util.List;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTComment;
|
import org.eclipse.cdt.core.dom.ast.IASTComment;
|
||||||
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.IASTMacroExpansion;
|
||||||
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;
|
||||||
|
@ -48,7 +49,7 @@ public class LocationMap implements ILocationResolver {
|
||||||
private ArrayList<ASTProblem> fProblems= new ArrayList<ASTProblem>();
|
private ArrayList<ASTProblem> fProblems= new ArrayList<ASTProblem>();
|
||||||
private ArrayList<ASTComment> fComments= new ArrayList<ASTComment>();
|
private ArrayList<ASTComment> fComments= new ArrayList<ASTComment>();
|
||||||
private ArrayList<ASTObjectStyleMacroDefinition> fBuiltinMacros= new ArrayList<ASTObjectStyleMacroDefinition>();
|
private ArrayList<ASTObjectStyleMacroDefinition> fBuiltinMacros= new ArrayList<ASTObjectStyleMacroDefinition>();
|
||||||
private IdentityHashMap<IMacroBinding, List<IASTName>> fMacroReferences= new IdentityHashMap<IMacroBinding, List<IASTName>>();
|
private ArrayList<IASTName> fMacroReferences= new ArrayList<IASTName>();
|
||||||
|
|
||||||
private LocationCtxFile fRootContext= null;
|
private LocationCtxFile fRootContext= null;
|
||||||
private LocationCtx fCurrentContext= null;
|
private LocationCtx fCurrentContext= null;
|
||||||
|
@ -157,27 +158,22 @@ public class LocationMap implements ILocationResolver {
|
||||||
int endNumber= getSequenceNumberForOffset(endOffset);
|
int endNumber= getSequenceNumberForOffset(endOffset);
|
||||||
final int length= endNumber-nameNumber;
|
final int length= endNumber-nameNumber;
|
||||||
|
|
||||||
|
ASTMacroReferenceName expansion= new ASTMacroReferenceName(fTranslationUnit, nameNumber, nameEndNumber, macro, null);
|
||||||
for (int i = 0; i < implicitMacroReferences.length; i++) {
|
for (int i = 0; i < implicitMacroReferences.length; i++) {
|
||||||
ASTMacroReferenceName name = (ASTMacroReferenceName) implicitMacroReferences[i];
|
ASTMacroReferenceName name = (ASTMacroReferenceName) implicitMacroReferences[i];
|
||||||
name.setOffsetAndLength(nameNumber, length);
|
name.setOffsetAndLength(nameNumber, length);
|
||||||
addMacroReference((IMacroBinding) name.getBinding(), name);
|
name.setParent(expansion);
|
||||||
|
addMacroReference(name);
|
||||||
}
|
}
|
||||||
|
addMacroReference(expansion);
|
||||||
ASTMacroReferenceName expansion= new ASTMacroReferenceName(fTranslationUnit, nameNumber, nameEndNumber, macro, null);
|
|
||||||
addMacroReference(macro, expansion);
|
|
||||||
|
|
||||||
fCurrentContext= new LocationCtxMacroExpansion(this, (LocationCtxContainer) fCurrentContext, nameOffset, endOffset, endNumber, contextLength, imageLocations, expansion);
|
fCurrentContext= new LocationCtxMacroExpansion(this, (LocationCtxContainer) fCurrentContext, nameOffset, endOffset, endNumber, contextLength, imageLocations, expansion);
|
||||||
fLastChildInsertionOffset= 0;
|
fLastChildInsertionOffset= 0;
|
||||||
return fCurrentContext;
|
return fCurrentContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addMacroReference(IMacroBinding macro, IASTName name) {
|
private void addMacroReference(IASTName name) {
|
||||||
List<IASTName> list= fMacroReferences.get(macro);
|
fMacroReferences.add(name);
|
||||||
if (list == null) {
|
|
||||||
list= new ArrayList<IASTName>();
|
|
||||||
fMacroReferences.put(macro, list);
|
|
||||||
}
|
|
||||||
list.add(name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -310,7 +306,7 @@ public class LocationMap implements ILocationResolver {
|
||||||
// not using endOffset, compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset);
|
// not using endOffset, compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset);
|
||||||
final ASTUndef undef = new ASTUndef(fTranslationUnit, name, startOffset, nameOffset, nameEndOffset, definition);
|
final ASTUndef undef = new ASTUndef(fTranslationUnit, name, startOffset, nameOffset, nameEndOffset, definition);
|
||||||
fDirectives.add(undef);
|
fDirectives.add(undef);
|
||||||
addMacroReference(definition, undef.getMacroName());
|
addMacroReference(undef.getMacroName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRootNode(IASTTranslationUnit root) {
|
public void setRootNode(IASTTranslationUnit root) {
|
||||||
|
@ -351,15 +347,54 @@ public class LocationMap implements ILocationResolver {
|
||||||
return new String(ctx.getFilePath());
|
return new String(ctx.getFilePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
public IASTFileLocation getMappedFileLocation(int sequenceNumber, int length) {
|
public ASTFileLocation getMappedFileLocation(int sequenceNumber, int length) {
|
||||||
return fRootContext.findMappedFileLocation(sequenceNumber, length);
|
return fRootContext.findMappedFileLocation(sequenceNumber, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public char[] getUnpreprocessedSignature(IASTFileLocation loc) {
|
public char[] getUnpreprocessedSignature(IASTFileLocation loc) {
|
||||||
if (loc instanceof ASTFileLocation) {
|
ASTFileLocation floc= convertFileLocation(loc);
|
||||||
return ((ASTFileLocation) loc).getSource();
|
if (floc == null) {
|
||||||
}
|
return CharArrayUtils.EMPTY;
|
||||||
return CharArrayUtils.EMPTY;
|
}
|
||||||
|
return floc.getSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTMacroExpansion[] getMacroExpansions(IASTFileLocation loc) {
|
||||||
|
ASTFileLocation floc= convertFileLocation(loc);
|
||||||
|
if (floc == null) {
|
||||||
|
return new IASTMacroExpansion[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
LocationCtxFile ctx= floc.getLocationContext();
|
||||||
|
ArrayList<IASTMacroExpansion> list= new ArrayList<IASTMacroExpansion>();
|
||||||
|
|
||||||
|
ctx.collectExplicitMacroExpansions(floc.getNodeOffset(), floc.getNodeLength(), list);
|
||||||
|
return list.toArray(new IASTMacroExpansion[list.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ASTFileLocation convertFileLocation(IASTFileLocation loc) {
|
||||||
|
if (loc == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (loc instanceof ASTFileLocation) {
|
||||||
|
return (ASTFileLocation) loc;
|
||||||
|
}
|
||||||
|
final String fileName = loc.getFileName();
|
||||||
|
final int nodeOffset = loc.getNodeOffset();
|
||||||
|
final int nodeLength = loc.getNodeLength();
|
||||||
|
int sequenceNumber= getSequenceNumberForFileOffset(fileName, nodeOffset);
|
||||||
|
if (sequenceNumber < 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int length= 0;
|
||||||
|
if (nodeLength > 0) {
|
||||||
|
length= getSequenceNumberForFileOffset(fileName, nodeOffset + nodeLength-1)+1 - sequenceNumber;
|
||||||
|
if (length < 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getMappedFileLocation(sequenceNumber, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IASTNodeLocation[] getLocations(int sequenceNumber, int length) {
|
public IASTNodeLocation[] getLocations(int sequenceNumber, int length) {
|
||||||
|
@ -538,11 +573,23 @@ public class LocationMap implements ILocationResolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
public IASTName[] getReferences(IMacroBinding binding) {
|
public IASTName[] getReferences(IMacroBinding binding) {
|
||||||
List<IASTName> list= fMacroReferences.get(binding);
|
List<IASTName> result= new ArrayList<IASTName>();
|
||||||
if (list == null) {
|
for (IASTName name : fMacroReferences) {
|
||||||
return EMPTY_NAMES;
|
if (name.getBinding() == binding) {
|
||||||
|
result.add(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return list.toArray(new IASTName[list.size()]);
|
return result.toArray(new IASTName[result.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTName[] getImplicitMacroReferences(IASTName ref) {
|
||||||
|
List<IASTName> result= new ArrayList<IASTName>();
|
||||||
|
for (IASTName name : fMacroReferences) {
|
||||||
|
if (name.getParent() == ref) {
|
||||||
|
result.add(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toArray(new IASTName[result.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDependencyTree getDependencyTree() {
|
public IDependencyTree getDependencyTree() {
|
||||||
|
|
|
@ -11,13 +11,14 @@
|
||||||
package org.eclipse.cdt.internal.core.parser.scanner;
|
package org.eclipse.cdt.internal.core.parser.scanner;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.BitSet;
|
||||||
import java.util.IdentityHashMap;
|
import java.util.IdentityHashMap;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
import org.eclipse.cdt.core.parser.IProblem;
|
import org.eclipse.cdt.core.parser.IProblem;
|
||||||
import org.eclipse.cdt.core.parser.IToken;
|
import org.eclipse.cdt.core.parser.IToken;
|
||||||
import org.eclipse.cdt.core.parser.OffsetLimitReachedException;
|
import org.eclipse.cdt.core.parser.OffsetLimitReachedException;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
|
import org.eclipse.cdt.core.parser.util.CharArrayMap;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner.ImageLocationInfo.MacroImageLocationInfo;
|
import org.eclipse.cdt.internal.core.parser.scanner.ImageLocationInfo.MacroImageLocationInfo;
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner.ImageLocationInfo.ParameterImageLocationInfo;
|
import org.eclipse.cdt.internal.core.parser.scanner.ImageLocationInfo.ParameterImageLocationInfo;
|
||||||
|
@ -31,6 +32,7 @@ import org.eclipse.cdt.internal.core.parser.scanner.MacroDefinitionParser.TokenP
|
||||||
public class MacroExpander {
|
public class MacroExpander {
|
||||||
private static final int ORIGIN = OffsetLimitReachedException.ORIGIN_MACRO_EXPANSION;
|
private static final int ORIGIN = OffsetLimitReachedException.ORIGIN_MACRO_EXPANSION;
|
||||||
private static final Token END_TOKEN = new Token(IToken.tEND_OF_INPUT, null, 0, 0);
|
private static final Token END_TOKEN = new Token(IToken.tEND_OF_INPUT, null, 0, 0);
|
||||||
|
private static final TokenList EMPTY_TOKEN_LIST = new TokenList();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks the beginning and the end of the scope of a macro expansion. Necessary to properly
|
* Marks the beginning and the end of the scope of a macro expansion. Necessary to properly
|
||||||
|
@ -125,7 +127,7 @@ public class MacroExpander {
|
||||||
|
|
||||||
private final ILexerLog fLog;
|
private final ILexerLog fLog;
|
||||||
private final MacroDefinitionParser fDefinitionParser;
|
private final MacroDefinitionParser fDefinitionParser;
|
||||||
private final CharArrayObjectMap fDictionary;
|
private final CharArrayMap<PreprocessorMacro> fDictionary;
|
||||||
private final LocationMap fLocationMap;
|
private final LocationMap fLocationMap;
|
||||||
private final LexerOptions fLexOptions;
|
private final LexerOptions fLexOptions;
|
||||||
private ArrayList<IASTName> fImplicitMacroExpansions= new ArrayList<IASTName>();
|
private ArrayList<IASTName> fImplicitMacroExpansions= new ArrayList<IASTName>();
|
||||||
|
@ -134,8 +136,8 @@ public class MacroExpander {
|
||||||
private int fStartOffset;
|
private int fStartOffset;
|
||||||
private int fEndOffset;
|
private int fEndOffset;
|
||||||
|
|
||||||
public MacroExpander(ILexerLog log, CharArrayObjectMap dict, LocationMap locationMap, LexerOptions lexOptions) {
|
public MacroExpander(ILexerLog log, CharArrayMap<PreprocessorMacro> macroDictionary, LocationMap locationMap, LexerOptions lexOptions) {
|
||||||
fDictionary= dict;
|
fDictionary= macroDictionary;
|
||||||
fLocationMap= locationMap;
|
fLocationMap= locationMap;
|
||||||
fDefinitionParser= new MacroDefinitionParser();
|
fDefinitionParser= new MacroDefinitionParser();
|
||||||
fLexOptions= lexOptions;
|
fLexOptions= lexOptions;
|
||||||
|
@ -158,45 +160,144 @@ public class MacroExpander {
|
||||||
// setup input sequence
|
// setup input sequence
|
||||||
TokenSource input= new TokenSource(lexer, stopAtNewline);
|
TokenSource input= new TokenSource(lexer, stopAtNewline);
|
||||||
TokenList firstExpansion= new TokenList();
|
TokenList firstExpansion= new TokenList();
|
||||||
expandOne(identifier, macro, forbidden, input, firstExpansion);
|
expandOne(identifier, macro, forbidden, input, firstExpansion, null);
|
||||||
input.prepend(firstExpansion);
|
input.prepend(firstExpansion);
|
||||||
|
|
||||||
TokenList result= expandAll(input, forbidden);
|
TokenList result= expandAll(input, forbidden, null);
|
||||||
postProcessTokens(result);
|
postProcessTokens(result);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method for tracking macro expansions.
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public void expand(String beforeExpansion, MacroExpansionTracker tracker) {
|
||||||
|
Lexer lexer= new Lexer(beforeExpansion.toCharArray(), fLexOptions, fLog, this);
|
||||||
|
fImplicitMacroExpansions.clear();
|
||||||
|
fImageLocationInfos.clear();
|
||||||
|
|
||||||
|
try {
|
||||||
|
tracker.start(lexer);
|
||||||
|
Token identifier= lexer.nextToken();
|
||||||
|
if (identifier.getType() != IToken.tIDENTIFIER) {
|
||||||
|
tracker.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PreprocessorMacro macro= fDictionary.get(identifier.getCharImage());
|
||||||
|
if (macro == null) {
|
||||||
|
tracker.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lexer.nextToken();
|
||||||
|
|
||||||
|
fStartOffset= identifier.getOffset();
|
||||||
|
fEndOffset= identifier.getEndOffset();
|
||||||
|
fCompletionMode= false;
|
||||||
|
IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden= new IdentityHashMap<PreprocessorMacro, PreprocessorMacro>();
|
||||||
|
|
||||||
|
// setup input sequence
|
||||||
|
TokenSource input= new TokenSource(lexer, false);
|
||||||
|
TokenList firstExpansion= new TokenList();
|
||||||
|
expandOne(identifier, macro, forbidden, input, firstExpansion, tracker);
|
||||||
|
input.prepend(firstExpansion);
|
||||||
|
|
||||||
|
TokenList result= expandAll(input, forbidden, tracker);
|
||||||
|
tracker.finish(result, fEndOffset);
|
||||||
|
} catch (OffsetLimitReachedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expects that the identifier of the macro expansion has been consumed. Expands the macro consuming
|
* Expects that the identifier of the macro expansion has been consumed. Expands the macro consuming
|
||||||
* tokens from the input (to read the parameters) and stores the resulting tokens together
|
* tokens from the input (to read the parameters) and stores the resulting tokens together
|
||||||
* with boundary markers in the result token list.
|
* with boundary markers in the result token list.
|
||||||
* Returns the last token of the expansion.
|
* Returns the last token of the expansion.
|
||||||
*/
|
*/
|
||||||
private Token expandOne(Token lastConsumed, PreprocessorMacro macro, IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden, TokenSource input, TokenList result)
|
private Token expandOne(Token lastConsumed, PreprocessorMacro macro,
|
||||||
|
IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden, TokenSource input, TokenList result,
|
||||||
|
MacroExpansionTracker tracker)
|
||||||
throws OffsetLimitReachedException {
|
throws OffsetLimitReachedException {
|
||||||
result.append(new ExpansionBoundary(macro, true));
|
result.append(new ExpansionBoundary(macro, true));
|
||||||
if (macro.isFunctionStyle()) {
|
if (macro.isFunctionStyle()) {
|
||||||
final TokenSource[] argInputs= new TokenSource[macro.getParameterPlaceholderList().length];
|
final int paramCount = macro.getParameterPlaceholderList().length;
|
||||||
lastConsumed= parseArguments(input, (FunctionStyleMacro) macro, forbidden, argInputs);
|
final TokenSource[] argInputs= new TokenSource[paramCount];
|
||||||
TokenList[] clonedArgs= new TokenList[argInputs.length];
|
final BitSet paramUsage= getParamUsage(macro);
|
||||||
TokenList[] expandedArgs= new TokenList[argInputs.length];
|
if (tracker != null) {
|
||||||
for (int i = 0; i < argInputs.length; i++) {
|
tracker.startFunctionStyleMacro((Token) lastConsumed.clone());
|
||||||
final TokenSource argInput = argInputs[i];
|
}
|
||||||
clonedArgs[i]= argInput.cloneTokens();
|
lastConsumed= parseArguments(input, (FunctionStyleMacro) macro, forbidden, argInputs, tracker);
|
||||||
final TokenList expandedArg= expandAll(argInput, forbidden);
|
TokenList[] clonedArgs= new TokenList[paramCount];
|
||||||
expandedArgs[i]= expandedArg;
|
TokenList[] expandedArgs= new TokenList[paramCount];
|
||||||
|
for (int i = 0; i < paramCount; i++) {
|
||||||
|
final TokenSource argInput = argInputs[i];
|
||||||
|
final boolean needCopy= paramUsage.get(2*i);
|
||||||
|
final boolean needExpansion = paramUsage.get(2*i+1);
|
||||||
|
clonedArgs[i]= needCopy ? argInput.cloneTokens() : EMPTY_TOKEN_LIST;
|
||||||
|
expandedArgs[i]= needExpansion ? expandAll(argInput, forbidden, tracker) : EMPTY_TOKEN_LIST;
|
||||||
|
if (!needExpansion) {
|
||||||
|
executeScopeMarkers(argInput, forbidden);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tracker != null) {
|
||||||
|
tracker.setExpandedMacroArgument(needExpansion ? expandedArgs[i] : null);
|
||||||
|
// make sure that the trailing arguments do not get expanded.
|
||||||
|
if (tracker.isDone()) {
|
||||||
|
paramUsage.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tracker == null) {
|
||||||
|
replaceArgs(macro, clonedArgs, expandedArgs, result);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (tracker.isRequestedStep()) {
|
||||||
|
TokenList replacement= new TokenList();
|
||||||
|
replaceArgs(macro, clonedArgs, expandedArgs, replacement);
|
||||||
|
tracker.storeFunctionStyleMacroReplacement(macro, replacement, result);
|
||||||
|
}
|
||||||
|
else if (tracker.isDone()) {
|
||||||
|
tracker.appendFunctionStyleMacro(result);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
replaceArgs(macro, clonedArgs, expandedArgs, result);
|
||||||
|
}
|
||||||
|
tracker.endFunctionStyleMacro();
|
||||||
}
|
}
|
||||||
replaceArgs(macro, clonedArgs, expandedArgs, result);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
objStyleTokenPaste(macro, result);
|
if (tracker == null) {
|
||||||
|
objStyleTokenPaste(macro, result);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (tracker.isRequestedStep()) {
|
||||||
|
TokenList replacement= new TokenList();
|
||||||
|
objStyleTokenPaste(macro, replacement);
|
||||||
|
tracker.storeObjectStyleMacroReplacement(macro, lastConsumed, replacement, result);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
objStyleTokenPaste(macro, result);
|
||||||
|
}
|
||||||
|
tracker.endObjectStyleMacro();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
result.append(new ExpansionBoundary(macro, false));
|
result.append(new ExpansionBoundary(macro, false));
|
||||||
return lastConsumed;
|
return lastConsumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TokenList expandAll(TokenSource input, IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden) throws OffsetLimitReachedException {
|
private void executeScopeMarkers(TokenSource input, IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden) {
|
||||||
|
Token t= input.removeFirst();
|
||||||
|
while(t != null) {
|
||||||
|
if (t.getType() == CPreprocessor.tSCOPE_MARKER) {
|
||||||
|
((ExpansionBoundary) t).execute(forbidden);
|
||||||
|
}
|
||||||
|
t= input.removeFirst();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private TokenList expandAll(TokenSource input, IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden,
|
||||||
|
MacroExpansionTracker tracker) throws OffsetLimitReachedException {
|
||||||
final TokenList result= new TokenList();
|
final TokenList result= new TokenList();
|
||||||
Token l= null;
|
Token l= null;
|
||||||
Token t= input.removeFirst();
|
Token t= input.removeFirst();
|
||||||
|
@ -207,9 +308,12 @@ public class MacroExpander {
|
||||||
t= input.removeFirst(); // don't change l
|
t= input.removeFirst(); // don't change l
|
||||||
continue;
|
continue;
|
||||||
case IToken.tIDENTIFIER:
|
case IToken.tIDENTIFIER:
|
||||||
PreprocessorMacro macro= (PreprocessorMacro) fDictionary.get(t.getCharImage());
|
PreprocessorMacro macro= fDictionary.get(t.getCharImage());
|
||||||
|
if (tracker != null && tracker.isDone()) {
|
||||||
|
result.append(t);
|
||||||
|
}
|
||||||
// tricky: don't mark function-style macros if you don't find the left parenthesis
|
// tricky: don't mark function-style macros if you don't find the left parenthesis
|
||||||
if (macro == null || (macro.isFunctionStyle() && !input.findLParenthesis())) {
|
else if (macro == null || (macro.isFunctionStyle() && !input.findLParenthesis())) {
|
||||||
result.append(t);
|
result.append(t);
|
||||||
}
|
}
|
||||||
else if (forbidden.containsKey(macro)) {
|
else if (forbidden.containsKey(macro)) {
|
||||||
|
@ -227,7 +331,7 @@ public class MacroExpander {
|
||||||
TokenList replacement= new TokenList();
|
TokenList replacement= new TokenList();
|
||||||
|
|
||||||
addSpacemarker(l, t, replacement); // start expansion
|
addSpacemarker(l, t, replacement); // start expansion
|
||||||
Token last= expandOne(t, macro, forbidden, input, replacement);
|
Token last= expandOne(t, macro, forbidden, input, replacement, tracker);
|
||||||
addSpacemarker(last, input.first(), replacement); // end expansion
|
addSpacemarker(last, input.first(), replacement); // end expansion
|
||||||
|
|
||||||
input.prepend(replacement);
|
input.prepend(replacement);
|
||||||
|
@ -262,12 +366,12 @@ public class MacroExpander {
|
||||||
if (l != null && t != null) {
|
if (l != null && t != null) {
|
||||||
final Object s1= l.fSource;
|
final Object s1= l.fSource;
|
||||||
final Object s2= t.fSource;
|
final Object s2= t.fSource;
|
||||||
if (s1 == s2 && s1 != null) {
|
if (s1 == s2 && s1 != null && l.getType() != CPreprocessor.tSPACE) {
|
||||||
if (l.getEndOffset() == t.getOffset()) {
|
if (l.getEndOffset() == t.getOffset()) {
|
||||||
target.append(new Token(CPreprocessor.tNOSPACE, null, 0, 0));
|
target.append(new Token(CPreprocessor.tNOSPACE, null, 0, 0));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
target.append(new Token(CPreprocessor.tSPACE, null, 0, 0));
|
target.append(new Token(CPreprocessor.tSPACE, s1, l.getEndOffset(), t.getOffset()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -276,9 +380,11 @@ public class MacroExpander {
|
||||||
/**
|
/**
|
||||||
* Expects that the identifier has been consumed.
|
* Expects that the identifier has been consumed.
|
||||||
* @param forbidden
|
* @param forbidden
|
||||||
|
* @param tracker
|
||||||
* @throws OffsetLimitReachedException
|
* @throws OffsetLimitReachedException
|
||||||
*/
|
*/
|
||||||
private Token parseArguments(TokenSource input, FunctionStyleMacro macro, IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden, TokenSource[] result) throws OffsetLimitReachedException {
|
private Token parseArguments(TokenSource input, FunctionStyleMacro macro, IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden, TokenSource[] result,
|
||||||
|
MacroExpansionTracker tracker) throws OffsetLimitReachedException {
|
||||||
final int argCount= macro.getParameterPlaceholderList().length;
|
final int argCount= macro.getParameterPlaceholderList().length;
|
||||||
final boolean hasVarargs= macro.hasVarArgs() != FunctionStyleMacro.NO_VAARGS;
|
final boolean hasVarargs= macro.hasVarArgs() != FunctionStyleMacro.NO_VAARGS;
|
||||||
final int requiredArgs= hasVarargs ? argCount-1 : argCount;
|
final int requiredArgs= hasVarargs ? argCount-1 : argCount;
|
||||||
|
@ -296,6 +402,17 @@ public class MacroExpander {
|
||||||
Token t= input.fetchFirst();
|
Token t= input.fetchFirst();
|
||||||
if (t == null) {
|
if (t == null) {
|
||||||
break loop;
|
break loop;
|
||||||
|
}
|
||||||
|
if (tracker != null) {
|
||||||
|
switch(t.getType()) {
|
||||||
|
case IToken.tEND_OF_INPUT:
|
||||||
|
case IToken.tCOMPLETION:
|
||||||
|
case CPreprocessor.tSCOPE_MARKER:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
tracker.addFunctionStyleMacroExpansionToken((Token) t.clone());
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
lastToken= t;
|
lastToken= t;
|
||||||
switch(t.getType()) {
|
switch(t.getType()) {
|
||||||
|
@ -414,7 +531,7 @@ public class MacroExpander {
|
||||||
|
|
||||||
case IToken.tPOUND:
|
case IToken.tPOUND:
|
||||||
addSpacemarker(l, t, result); // start stringify
|
addSpacemarker(l, t, result); // start stringify
|
||||||
StringBuffer buf= new StringBuffer();
|
StringBuilder buf= new StringBuilder();
|
||||||
buf.append('"');
|
buf.append('"');
|
||||||
if (n != null && n.getType() == CPreprocessor.tMACRO_PARAMETER) {
|
if (n != null && n.getType() == CPreprocessor.tMACRO_PARAMETER) {
|
||||||
idx= ((TokenParameterReference) n).getIndex();
|
idx= ((TokenParameterReference) n).getIndex();
|
||||||
|
@ -441,65 +558,65 @@ public class MacroExpander {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IToken.tPOUNDPOUND:
|
case IToken.tPOUNDPOUND:
|
||||||
if (pasteArg1 != null) {
|
Token pasteArg2= null;
|
||||||
Token pasteArg2= null;
|
TokenList rest= null;
|
||||||
TokenList rest= null;
|
if (n != null) {
|
||||||
if (n != null) {
|
if (n.getType() == CPreprocessor.tMACRO_PARAMETER) {
|
||||||
if (n.getType() == CPreprocessor.tMACRO_PARAMETER) {
|
TokenList arg;
|
||||||
idx= ((TokenParameterReference) n).getIndex();
|
idx= ((TokenParameterReference) n).getIndex();
|
||||||
if (idx < args.length) { // be defensive
|
if (idx < args.length) { // be defensive
|
||||||
TokenList arg= clone(args[idx]);
|
// gcc-extension
|
||||||
pasteArg2= arg.first();
|
if (idx == args.length-1 && macro.hasVarArgs() != FunctionStyleMacro.NO_VAARGS &&
|
||||||
|
pasteArg1 != null && pasteArg1.getType() == IToken.tCOMMA) { // no paste operation
|
||||||
// gcc-extension
|
arg= clone(expandedArgs[idx]);
|
||||||
if (idx == args.length-1 && macro.hasVarArgs() != FunctionStyleMacro.NO_VAARGS) {
|
if (arg.first() != null) {
|
||||||
if (pasteArg1.getType() == IToken.tCOMMA) { // no paste operation
|
result.append(pasteArg1);
|
||||||
if (arg.first() != null) {
|
rest= arg;
|
||||||
result.append(pasteArg1);
|
|
||||||
rest= arg;
|
|
||||||
}
|
|
||||||
pasteArg1= pasteArg2= null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
pasteArg1= pasteArg2= null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
arg= clone(args[idx]);
|
||||||
|
pasteArg2= arg.first();
|
||||||
if (pasteArg2 != null && arg.first() != arg.last()) {
|
if (pasteArg2 != null && arg.first() != arg.last()) {
|
||||||
rest= arg;
|
rest= arg;
|
||||||
rest.removeFirst();
|
rest.removeFirst();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
idx= -1;
|
||||||
|
pasteArg2= n;
|
||||||
|
}
|
||||||
|
t= n;
|
||||||
|
n= (Token) n.getNext();
|
||||||
|
pasteNext= n != null && n.getType() == IToken.tPOUNDPOUND;
|
||||||
|
|
||||||
|
generated= tokenpaste(pasteArg1, pasteArg2, macro);
|
||||||
|
pasteArg1= null;
|
||||||
|
|
||||||
|
if (generated != null) {
|
||||||
|
if (pasteNext && rest == null) {
|
||||||
|
pasteArg1= generated; // no need to mark spaces, done ahead
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
idx= -1;
|
result.append(generated);
|
||||||
pasteArg2= n;
|
addSpacemarker(pasteArg2, rest == null ? n : rest.first(), result); // end token paste
|
||||||
}
|
}
|
||||||
t= n;
|
}
|
||||||
n= (Token) n.getNext();
|
if (rest != null) {
|
||||||
pasteNext= n != null && n.getType() == IToken.tPOUNDPOUND;
|
if (pasteNext) {
|
||||||
|
pasteArg1= rest.last();
|
||||||
generated= tokenpaste(pasteArg1, pasteArg2, macro);
|
if (pasteArg1 != null) {
|
||||||
pasteArg1= null;
|
result.appendAllButLast(rest);
|
||||||
|
addSpacemarker(result.last(), pasteArg1, result); // start token paste
|
||||||
if (generated != null) {
|
|
||||||
if (pasteNext && rest == null) {
|
|
||||||
pasteArg1= generated; // no need to mark spaces, done ahead
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result.append(generated);
|
|
||||||
addSpacemarker(pasteArg2, rest == null ? n : rest.first(), result); // end token paste
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rest != null) {
|
else {
|
||||||
if (pasteNext) {
|
result.appendAll(rest);
|
||||||
pasteArg1= rest.last();
|
if (idx >= 0) {
|
||||||
if (pasteArg1 != null) {
|
addSpacemarker(t, n, result); // end argument replacement
|
||||||
result.appendAllButLast(rest);
|
|
||||||
addSpacemarker(result.last(), pasteArg1, result); // start token paste
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result.appendAll(rest);
|
|
||||||
if (idx >= 0) {
|
|
||||||
addSpacemarker(t, n, result); // end argument replacement
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -519,6 +636,53 @@ public class MacroExpander {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BitSet getParamUsage(PreprocessorMacro macro) {
|
||||||
|
final BitSet result= new BitSet();
|
||||||
|
final TokenList replacement= macro.getTokens(fDefinitionParser, fLexOptions);
|
||||||
|
|
||||||
|
Token l= null;
|
||||||
|
Token n;
|
||||||
|
for (Token t= replacement.first(); t != null; l=t, t=n) {
|
||||||
|
n= (Token) t.getNext();
|
||||||
|
switch(t.getType()) {
|
||||||
|
case CPreprocessor.tMACRO_PARAMETER:
|
||||||
|
int idx= 2*((TokenParameterReference) t).getIndex();
|
||||||
|
if (n == null || n.getType() != IToken.tPOUNDPOUND) {
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
result.set(idx);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IToken.tPOUND:
|
||||||
|
if (n != null && n.getType() == CPreprocessor.tMACRO_PARAMETER) {
|
||||||
|
idx= ((TokenParameterReference) n).getIndex();
|
||||||
|
result.set(2*idx);
|
||||||
|
t= n; n= (Token) n.getNext();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IToken.tPOUNDPOUND:
|
||||||
|
if (n != null) {
|
||||||
|
if (n.getType() == CPreprocessor.tMACRO_PARAMETER) {
|
||||||
|
idx= ((TokenParameterReference) n).getIndex();
|
||||||
|
|
||||||
|
// gcc-extension
|
||||||
|
if (l != null && l.getType() == IToken.tCOMMA && macro.hasVarArgs() != FunctionStyleMacro.NO_VAARGS
|
||||||
|
&& idx == macro.getParameterPlaceholderList().length-1) {
|
||||||
|
result.set(2*idx+1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.set(2*idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t= n; n= (Token) n.getNext();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private void objStyleTokenPaste(PreprocessorMacro macro, TokenList result) {
|
private void objStyleTokenPaste(PreprocessorMacro macro, TokenList result) {
|
||||||
TokenList replacement= clone(macro.getTokens(fDefinitionParser, fLexOptions));
|
TokenList replacement= clone(macro.getTokens(fDefinitionParser, fLexOptions));
|
||||||
|
|
||||||
|
@ -574,6 +738,9 @@ public class MacroExpander {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Token tokenpaste(Token arg1, Token arg2, PreprocessorMacro macro) {
|
private Token tokenpaste(Token arg1, Token arg2, PreprocessorMacro macro) {
|
||||||
|
if (arg1 == null) {
|
||||||
|
return arg2;
|
||||||
|
}
|
||||||
if (arg2 == null) {
|
if (arg2 == null) {
|
||||||
return arg1;
|
return arg1;
|
||||||
}
|
}
|
||||||
|
@ -598,7 +765,7 @@ public class MacroExpander {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stringify(TokenList tokenList, StringBuffer buf) {
|
private void stringify(TokenList tokenList, StringBuilder buf) {
|
||||||
Token t= tokenList.first();
|
Token t= tokenList.first();
|
||||||
if (t == null) {
|
if (t == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -608,8 +775,7 @@ public class MacroExpander {
|
||||||
boolean space= false;
|
boolean space= false;
|
||||||
for (; t != null; l=t, t=n) {
|
for (; t != null; l=t, t=n) {
|
||||||
n= (Token) t.getNext();
|
n= (Token) t.getNext();
|
||||||
if (!space && l != null && l.fSource != null && l.fSource == t.fSource &&
|
if (!space && hasImplicitSpace(l, t)) {
|
||||||
l.getEndOffset() != t.getOffset()) {
|
|
||||||
buf.append(' ');
|
buf.append(' ');
|
||||||
space= true;
|
space= true;
|
||||||
}
|
}
|
||||||
|
@ -695,4 +861,10 @@ public class MacroExpander {
|
||||||
l= t;
|
l= t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static boolean hasImplicitSpace(Token l, Token t) {
|
||||||
|
return l != null &&
|
||||||
|
l.fSource != null && l.fSource == t.fSource &&
|
||||||
|
l.getEndOffset() != t.getOffset() && t.getType() != CPreprocessor.tSPACE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* 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.parser.scanner;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
|
||||||
|
import org.eclipse.cdt.core.dom.rewrite.MacroExpansionExplorer.IMacroExpansionStep;
|
||||||
|
import org.eclipse.text.edits.ReplaceEdit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation for {@link IMacroExpansionStep}.
|
||||||
|
*/
|
||||||
|
public class MacroExpansionStep implements IMacroExpansionStep {
|
||||||
|
private final String fBefore;
|
||||||
|
private final IMacroBinding fMacroDefinition;
|
||||||
|
private final ReplaceEdit[] fReplacements;
|
||||||
|
|
||||||
|
public MacroExpansionStep(String before, IMacroBinding def, ReplaceEdit[] replacements) {
|
||||||
|
fBefore= before;
|
||||||
|
fReplacements= replacements;
|
||||||
|
fMacroDefinition= def;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCodeBeforeStep() {
|
||||||
|
return fBefore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCodeAfterStep() {
|
||||||
|
StringBuilder result= new StringBuilder();
|
||||||
|
int offset= 0;
|
||||||
|
for (int i = 0; i < fReplacements.length; i++) {
|
||||||
|
ReplaceEdit r= fReplacements[i];
|
||||||
|
result.append(fBefore, offset, r.getOffset());
|
||||||
|
result.append(r.getText());
|
||||||
|
offset= r.getExclusiveEnd();
|
||||||
|
}
|
||||||
|
result.append(fBefore, offset, fBefore.length());
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMacroBinding getExpandedMacro() {
|
||||||
|
return fMacroDefinition;
|
||||||
|
}
|
||||||
|
public ReplaceEdit[] getReplacements() {
|
||||||
|
return fReplacements;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,348 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2007 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.parser.scanner;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
|
||||||
|
import org.eclipse.cdt.core.parser.IToken;
|
||||||
|
import org.eclipse.text.edits.ReplaceEdit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collects information while macro expansion is performed.
|
||||||
|
*/
|
||||||
|
public class MacroExpansionTracker {
|
||||||
|
public class MacroInfo {
|
||||||
|
private TokenList fMacroCall= new TokenList();
|
||||||
|
private ArrayList<TokenList> fArguments= new ArrayList<TokenList>();
|
||||||
|
|
||||||
|
public MacroInfo(Token identifier) {
|
||||||
|
fMacroCall.append(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setArgument(TokenList tokenList) {
|
||||||
|
fArguments.add(tokenList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final int fStepToTrack;
|
||||||
|
|
||||||
|
private int fStepCount;
|
||||||
|
private String fPreStep;
|
||||||
|
private ReplaceEdit fReplacement;
|
||||||
|
private IMacroBinding fMacroDefinition;
|
||||||
|
|
||||||
|
private Lexer fLexer;
|
||||||
|
private String fReplacementText= ""; //$NON-NLS-1$
|
||||||
|
private LinkedList<MacroInfo> fMacroStack= new LinkedList<MacroInfo>();
|
||||||
|
|
||||||
|
private IToken fReplaceFrom;
|
||||||
|
private IToken fReplaceTo;
|
||||||
|
|
||||||
|
public MacroExpansionTracker(int stepToTrack) {
|
||||||
|
fStepToTrack= stepToTrack;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the requested step has already been encountered.
|
||||||
|
*/
|
||||||
|
public boolean isDone() {
|
||||||
|
return fStepCount > fStepToTrack;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether we are currently looking at the requested step.
|
||||||
|
*/
|
||||||
|
public boolean isRequestedStep() {
|
||||||
|
return fStepCount == fStepToTrack;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the total amount of steps encountered so far.
|
||||||
|
*/
|
||||||
|
public int getStepCount() {
|
||||||
|
return fStepCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the code as it looks like just before performing the step that was tracked.
|
||||||
|
*/
|
||||||
|
public String getCodeBeforeStep() {
|
||||||
|
return fPreStep;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the replacement that represents the change by the step that was tracked.
|
||||||
|
*/
|
||||||
|
public ReplaceEdit getReplacement() {
|
||||||
|
return fReplacement;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the macro that is expanded in the step that was tracked.
|
||||||
|
*/
|
||||||
|
public IMacroBinding getExpandedMacro() {
|
||||||
|
return fMacroDefinition;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Informs the tracker that macro expansion is started.
|
||||||
|
*/
|
||||||
|
void start(Lexer lexer) {
|
||||||
|
fLexer= lexer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Informs the tracker that the expansion is done.
|
||||||
|
* @param result the list of tokens after performing partial expansion up to the step that was
|
||||||
|
* tracked.
|
||||||
|
* @param endOffset the end offset of the input that was read from the lexer.
|
||||||
|
*/
|
||||||
|
void finish(TokenList result, int endOffset) {
|
||||||
|
final char[] lexInput = fLexer.getInput();
|
||||||
|
if (!isDone()) {
|
||||||
|
// special case we compute the entire expansion as one step, the result contains the
|
||||||
|
// expanded text
|
||||||
|
StringBuilder replacementText= new StringBuilder();
|
||||||
|
toString(result, lexInput, replacementText, replacementText, replacementText);
|
||||||
|
fPreStep= new String(lexInput);
|
||||||
|
fReplacement= new ReplaceEdit(0, endOffset, replacementText.toString());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// the regular case the result contains the text before the step
|
||||||
|
StringBuilder before= new StringBuilder();
|
||||||
|
StringBuilder replace= new StringBuilder();
|
||||||
|
StringBuilder after= new StringBuilder();
|
||||||
|
toString(result, lexInput, before, replace, after);
|
||||||
|
int offset= before.length();
|
||||||
|
before.append(replace).append(after);
|
||||||
|
before.append(lexInput, endOffset, lexInput.length-endOffset);
|
||||||
|
fPreStep= before.toString();
|
||||||
|
fReplacement= new ReplaceEdit(offset, replace.length(), fReplacementText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* There was no macro at the beginning of the input.
|
||||||
|
*/
|
||||||
|
void fail() {
|
||||||
|
fPreStep= new String(fLexer.getInput());
|
||||||
|
fReplacement= new ReplaceEdit(0, 0, ""); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
private void toString(TokenList tokenList, char[] rootInput, StringBuilder before, StringBuilder replace, StringBuilder after) {
|
||||||
|
StringBuilder buf= before;
|
||||||
|
Token t= tokenList.first();
|
||||||
|
if (t == null) {
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
Token l= null;
|
||||||
|
Token n;
|
||||||
|
for (; t != null; l=t, t=n) {
|
||||||
|
n= (Token) t.getNext();
|
||||||
|
if (MacroExpander.hasImplicitSpace(l, t)) {
|
||||||
|
char[] input= getInputForSource(l.fSource, rootInput);
|
||||||
|
if (input == null) {
|
||||||
|
buf.append(' ');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final int from = l.getEndOffset();
|
||||||
|
final int to = t.getOffset();
|
||||||
|
buf.append(input, from, to-from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (t == fReplaceFrom) {
|
||||||
|
buf= replace;
|
||||||
|
}
|
||||||
|
char[] input= getInputForSource(t.fSource, rootInput);
|
||||||
|
if (input == null) {
|
||||||
|
buf.append(t.getCharImage());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buf.append(input, t.getOffset(), t.getLength());
|
||||||
|
}
|
||||||
|
if (t == fReplaceTo) {
|
||||||
|
buf= after;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private char[] getInputForSource(Object source, char[] rootInput) {
|
||||||
|
if (source instanceof MacroExpander) {
|
||||||
|
return rootInput;
|
||||||
|
}
|
||||||
|
if (source instanceof PreprocessorMacro) {
|
||||||
|
return ((PreprocessorMacro) source).getExpansionImage();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Informs the tracker that a function-style expansion is started.
|
||||||
|
* @param identifier the identifier token for the macro expansion.
|
||||||
|
*/
|
||||||
|
public void startFunctionStyleMacro(Token identifier) {
|
||||||
|
fMacroStack.add(new MacroInfo(identifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All tokens defining a function-style macro expansion are reported.
|
||||||
|
*/
|
||||||
|
public void addFunctionStyleMacroExpansionToken(Token t) {
|
||||||
|
fMacroStack.getLast().fMacroCall.append(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The expanded arguments for the function-style macro expansion are reported.
|
||||||
|
* @param tokenList the expanded argument, or <code>null</code> if it should not
|
||||||
|
* be expanded.
|
||||||
|
*/
|
||||||
|
public void setExpandedMacroArgument(TokenList tokenList) {
|
||||||
|
fMacroStack.getLast().setArgument(tokenList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called for the requested step.
|
||||||
|
* @param macro the macro expanded in the requested step.
|
||||||
|
* @param replacement the replacement for the expansion.
|
||||||
|
* @param result a list to store the macro call with the arguments substituted in.
|
||||||
|
*/
|
||||||
|
public void storeFunctionStyleMacroReplacement(PreprocessorMacro macro, TokenList replacement, TokenList result) {
|
||||||
|
MacroInfo minfo= fMacroStack.getLast();
|
||||||
|
fMacroDefinition= macro;
|
||||||
|
fReplaceFrom= minfo.fMacroCall.first();
|
||||||
|
appendFunctionStyleMacro(result);
|
||||||
|
fReplaceTo= result.last();
|
||||||
|
StringBuilder buf= new StringBuilder();
|
||||||
|
toString(replacement, fLexer.getInput(), buf, buf, buf);
|
||||||
|
fReplacementText= buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append the current function-style macro with the arguments substituted.
|
||||||
|
*/
|
||||||
|
public void appendFunctionStyleMacro(TokenList result) {
|
||||||
|
MacroInfo minfo= fMacroStack.getLast();
|
||||||
|
boolean active= true;
|
||||||
|
int nesting= -1;
|
||||||
|
int pcount= 0;
|
||||||
|
|
||||||
|
Token n;
|
||||||
|
Token l= null;
|
||||||
|
for (Token t = minfo.fMacroCall.first(); t != null; l=t, t=n) {
|
||||||
|
n = (Token) t.getNext();
|
||||||
|
switch (t.getType()) {
|
||||||
|
case IToken.tLPAREN:
|
||||||
|
if (active) {
|
||||||
|
result.append(t);
|
||||||
|
}
|
||||||
|
// the first one sets nesting to zero.
|
||||||
|
++nesting;
|
||||||
|
if (nesting == 0) {
|
||||||
|
if (pcount < minfo.fArguments.size()) {
|
||||||
|
TokenList p = minfo.fArguments.get(pcount);
|
||||||
|
if (p != null) {
|
||||||
|
active = false;
|
||||||
|
addSpacemarker(t, n, result);
|
||||||
|
result.appendAll(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IToken.tRPAREN:
|
||||||
|
if (!active && nesting == 0) {
|
||||||
|
addSpacemarker(l, t, result);
|
||||||
|
active= true;
|
||||||
|
}
|
||||||
|
if (active) {
|
||||||
|
result.append(t);
|
||||||
|
}
|
||||||
|
if (nesting > 0) {
|
||||||
|
nesting--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IToken.tCOMMA:
|
||||||
|
if (nesting == 0) {
|
||||||
|
if (++pcount < minfo.fArguments.size()) {
|
||||||
|
if (!active) {
|
||||||
|
addSpacemarker(l, t, result);
|
||||||
|
}
|
||||||
|
result.append(t);
|
||||||
|
TokenList p = minfo.fArguments.get(pcount);
|
||||||
|
active = p == null;
|
||||||
|
if (!active) {
|
||||||
|
addSpacemarker(t, n, result);
|
||||||
|
result.appendAll(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (active) {
|
||||||
|
result.append(t);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (active) {
|
||||||
|
result.append(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addSpacemarker(Token l, Token t, TokenList target) {
|
||||||
|
Token tl= target.last();
|
||||||
|
if (tl != null && tl.getType() == CPreprocessor.tSPACE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (l != null && t != null) {
|
||||||
|
final Object s1= l.fSource;
|
||||||
|
final Object s2= t.fSource;
|
||||||
|
if (s1 == s2 && s1 != null && l.getType() != CPreprocessor.tSPACE) {
|
||||||
|
if (l.getEndOffset() != t.getOffset()) {
|
||||||
|
target.append(new Token(CPreprocessor.tSPACE, s1, l.getEndOffset(), t.getOffset()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Informs the tracker that the function style macro has been expanded.
|
||||||
|
*/
|
||||||
|
public void endFunctionStyleMacro() {
|
||||||
|
fStepCount++;
|
||||||
|
fMacroStack.removeLast();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called for the requested step
|
||||||
|
* @param macro the macro expanded in the requested step.
|
||||||
|
* @param identifier the token that gets replaced.
|
||||||
|
* @param replacement the replacement
|
||||||
|
* @param result a list to store the macro in.
|
||||||
|
*/
|
||||||
|
public void storeObjectStyleMacroReplacement(PreprocessorMacro macro, Token identifier, TokenList replacement, TokenList result) {
|
||||||
|
fMacroDefinition= macro;
|
||||||
|
fReplaceFrom= fReplaceTo= identifier;
|
||||||
|
result.append(identifier);
|
||||||
|
StringBuilder buf= new StringBuilder();
|
||||||
|
toString(replacement, fLexer.getInput(), buf, buf, buf);
|
||||||
|
fReplacementText= buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Informs the tracker that an object style macro has been expanded.
|
||||||
|
*/
|
||||||
|
public void endObjectStyleMacro() {
|
||||||
|
fStepCount++;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,184 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* 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.parser.scanner;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTMacroExpansion;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
|
import org.eclipse.cdt.core.dom.rewrite.MacroExpansionExplorer;
|
||||||
|
import org.eclipse.jface.text.IRegion;
|
||||||
|
import org.eclipse.text.edits.ReplaceEdit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delegates the task of exploring macro expansions to simpler explorers dealing with
|
||||||
|
* a single macro, only.
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public class MultiMacroExpansionExplorer extends MacroExpansionExplorer {
|
||||||
|
private static final class ASTFileLocation implements IASTFileLocation {
|
||||||
|
private final String fFilePath;
|
||||||
|
private final int fOffset;
|
||||||
|
private final int fLength;
|
||||||
|
|
||||||
|
private ASTFileLocation(String filePath, int offset, int length) {
|
||||||
|
fFilePath= filePath;
|
||||||
|
fOffset= offset;
|
||||||
|
fLength= length;
|
||||||
|
}
|
||||||
|
public int getNodeOffset() {return fOffset;}
|
||||||
|
public int getNodeLength() {return fLength;}
|
||||||
|
public String getFileName() {return fFilePath;}
|
||||||
|
|
||||||
|
public int getStartingLineNumber() {return 0;}
|
||||||
|
public int getEndingLineNumber() {return 0;}
|
||||||
|
public IASTFileLocation asFileLocation() {return this;}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final char[] fSource;
|
||||||
|
private final int[] fBoundaries;
|
||||||
|
private final SingleMacroExpansionExplorer[] fDelegates;
|
||||||
|
|
||||||
|
public MultiMacroExpansionExplorer(IASTTranslationUnit tu, IASTFileLocation loc) {
|
||||||
|
if (tu == null || loc == null || loc.getNodeLength() == 0) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
final ILocationResolver resolver = (ILocationResolver) tu.getAdapter(ILocationResolver.class);
|
||||||
|
if (resolver == null) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
final IASTMacroExpansion[] expansions = resolver.getMacroExpansions(loc);
|
||||||
|
final int count= expansions.length;
|
||||||
|
if (count > 0) {
|
||||||
|
int from= loc.getNodeOffset();
|
||||||
|
int to= from+loc.getNodeLength();
|
||||||
|
|
||||||
|
final int lfrom = expansions[0].asFileLocation().getNodeOffset();
|
||||||
|
final IASTFileLocation l= expansions[count-1].asFileLocation();
|
||||||
|
final int lto= l.getNodeOffset() + l.getNodeLength();
|
||||||
|
|
||||||
|
if (lfrom < from || lto > to) {
|
||||||
|
from= Math.min(from, lfrom);
|
||||||
|
to= Math.max(to, lto);
|
||||||
|
loc= new ASTFileLocation(loc.getFileName(), from, to-from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fSource= resolver.getUnpreprocessedSignature(loc);
|
||||||
|
fBoundaries= new int[count*2+1];
|
||||||
|
fDelegates= new SingleMacroExpansionExplorer[count];
|
||||||
|
|
||||||
|
final int firstOffset= loc.getNodeOffset();
|
||||||
|
int bidx= -1;
|
||||||
|
int didx= -1;
|
||||||
|
for (IASTMacroExpansion expansion : expansions) {
|
||||||
|
IASTName ref= expansion.getMacroReference();
|
||||||
|
if (ref != null) {
|
||||||
|
IASTFileLocation refLoc= expansion.asFileLocation();
|
||||||
|
int from= refLoc.getNodeOffset()-firstOffset;
|
||||||
|
int to= from+refLoc.getNodeLength();
|
||||||
|
fBoundaries[++bidx]= from;
|
||||||
|
fBoundaries[++bidx]= to;
|
||||||
|
fDelegates[++didx]= new SingleMacroExpansionExplorer(new String(fSource, from, to-from), ref,
|
||||||
|
resolver.getImplicitMacroReferences(ref));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fBoundaries[++bidx]= fSource.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultiMacroExpansionExplorer(final IASTTranslationUnit tu, final IRegion loc) {
|
||||||
|
this(tu, new ASTFileLocation(tu.getFilePath(), loc.getOffset(), loc.getLength()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IMacroExpansionStep getFullExpansion() {
|
||||||
|
List<ReplaceEdit> edits = combineReplaceEdits(fDelegates.length);
|
||||||
|
return new MacroExpansionStep(new String(fSource), null, edits.toArray(new ReplaceEdit[edits.size()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combines the replace edits of the leading delegates.
|
||||||
|
*/
|
||||||
|
private List<ReplaceEdit> combineReplaceEdits(int count) {
|
||||||
|
ArrayList<ReplaceEdit> edits= new ArrayList<ReplaceEdit>();
|
||||||
|
for (int i=0; i < count; i++) {
|
||||||
|
IMacroExpansionStep step= fDelegates[i].getFullExpansion();
|
||||||
|
shiftAndAddEdits(fBoundaries[2*i], step.getReplacements(), edits);
|
||||||
|
}
|
||||||
|
return edits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shifts and adds the replace edits to the target list.
|
||||||
|
*/
|
||||||
|
private void shiftAndAddEdits(final int shift, ReplaceEdit[] stepEdits, List<ReplaceEdit> target) {
|
||||||
|
for (int j = 0; j < stepEdits.length; j++) {
|
||||||
|
final ReplaceEdit r = stepEdits[j];
|
||||||
|
final String rtext = r.getText();
|
||||||
|
target.add(new ReplaceEdit(shift+r.getOffset(), r.getLength(), rtext));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getExpansionStepCount() {
|
||||||
|
int result= 0;
|
||||||
|
for (int i=0; i < fDelegates.length; i++) {
|
||||||
|
result+= fDelegates[i].getExpansionStepCount();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IMacroExpansionStep getExpansionStep(int step) throws IndexOutOfBoundsException {
|
||||||
|
if (step < 0) {
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
int i;
|
||||||
|
MacroExpansionStep dresult= null;
|
||||||
|
StringBuilder before= new StringBuilder();
|
||||||
|
before.append(fSource, 0, fBoundaries[0]);
|
||||||
|
|
||||||
|
for (i=0; i < fDelegates.length; i++) {
|
||||||
|
final SingleMacroExpansionExplorer delegate = fDelegates[i];
|
||||||
|
int dsteps= delegate.getExpansionStepCount();
|
||||||
|
if (step < dsteps) {
|
||||||
|
dresult= delegate.getExpansionStep(step);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
before.append(delegate.getFullExpansion().getCodeAfterStep());
|
||||||
|
appendGap(before, i);
|
||||||
|
step-= dsteps;
|
||||||
|
}
|
||||||
|
if (dresult == null) {
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
|
||||||
|
final int shift= before.length();
|
||||||
|
final int end= fBoundaries[2*i+1];
|
||||||
|
before.append(dresult.getCodeBeforeStep());
|
||||||
|
before.append(fSource, end, fSource.length-end);
|
||||||
|
|
||||||
|
List<ReplaceEdit> replacements= new ArrayList<ReplaceEdit>();
|
||||||
|
shiftAndAddEdits(shift, dresult.getReplacements(), replacements);
|
||||||
|
return new MacroExpansionStep(before.toString(), dresult.getExpandedMacro(), replacements.toArray(new ReplaceEdit[replacements.size()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendGap(StringBuilder result, int i) {
|
||||||
|
int idx= 2*i+1;
|
||||||
|
int gapFrom= fBoundaries[idx];
|
||||||
|
int gapTo= fBoundaries[++idx];
|
||||||
|
result.append(fSource, gapFrom, gapTo-gapFrom);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* 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.parser.scanner;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
|
import org.eclipse.cdt.core.dom.rewrite.MacroExpansionExplorer;
|
||||||
|
import org.eclipse.cdt.core.parser.util.CharArrayMap;
|
||||||
|
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
|
||||||
|
import org.eclipse.text.edits.ReplaceEdit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs step by step macro expansion for an exact macro expansion location.
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public class SingleMacroExpansionExplorer extends MacroExpansionExplorer {
|
||||||
|
|
||||||
|
private static final LexerOptions LEX_OPTIONS= new LexerOptions();
|
||||||
|
static {
|
||||||
|
LEX_OPTIONS.fCreateImageLocations= false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String fInput;
|
||||||
|
private final CharArrayMap<PreprocessorMacro> fDictionary;
|
||||||
|
private MacroExpansionStep fFullExpansion;
|
||||||
|
private int fExpansionCount;
|
||||||
|
|
||||||
|
public SingleMacroExpansionExplorer(String input, IASTName ref, IASTName[] implicitRefs) {
|
||||||
|
fInput= input;
|
||||||
|
fDictionary= createDictionary(ref, implicitRefs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CharArrayMap<PreprocessorMacro> createDictionary(IASTName ref, IASTName[] implicitRefs) {
|
||||||
|
// mstodo handle dynamic style macros
|
||||||
|
// mstodo clone index-macros
|
||||||
|
CharArrayMap<PreprocessorMacro> map= new CharArrayMap<PreprocessorMacro>(implicitRefs.length+1);
|
||||||
|
addMacroDefinition(map, ref);
|
||||||
|
for (IASTName name : implicitRefs) {
|
||||||
|
addMacroDefinition(map, name);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addMacroDefinition(CharArrayMap<PreprocessorMacro> map, IASTName name) {
|
||||||
|
IBinding binding= name.getBinding();
|
||||||
|
if (binding instanceof PreprocessorMacro) {
|
||||||
|
map.put(name.toCharArray(), (PreprocessorMacro) binding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IMacroExpansionStep getFullExpansion() {
|
||||||
|
computeExpansion();
|
||||||
|
return fFullExpansion;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getExpansionStepCount() {
|
||||||
|
computeExpansion();
|
||||||
|
return fExpansionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void computeExpansion() {
|
||||||
|
MacroExpander expander= new MacroExpander(ILexerLog.NULL, fDictionary, null, LEX_OPTIONS);
|
||||||
|
MacroExpansionTracker tracker= new MacroExpansionTracker(Integer.MAX_VALUE);
|
||||||
|
expander.expand(fInput, tracker);
|
||||||
|
|
||||||
|
fExpansionCount= tracker.getStepCount();
|
||||||
|
ReplaceEdit r= tracker.getReplacement();
|
||||||
|
ReplaceEdit[] replacements= r==null ? new ReplaceEdit[0] : new ReplaceEdit[]{r};
|
||||||
|
fFullExpansion= new MacroExpansionStep(fInput, null, replacements);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MacroExpansionStep getExpansionStep(int step) throws IndexOutOfBoundsException {
|
||||||
|
computeExpansion();
|
||||||
|
if (step < 0 || step >= fExpansionCount) {
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
MacroExpander expander= new MacroExpander(ILexerLog.NULL, fDictionary, null, LEX_OPTIONS);
|
||||||
|
MacroExpansionTracker tracker= new MacroExpansionTracker(step);
|
||||||
|
expander.expand(fInput, tracker);
|
||||||
|
|
||||||
|
fExpansionCount= tracker.getStepCount();
|
||||||
|
ReplaceEdit r= tracker.getReplacement();
|
||||||
|
ReplaceEdit[] replacements= r==null ? new ReplaceEdit[0] : new ReplaceEdit[]{r};
|
||||||
|
return new MacroExpansionStep(tracker.getCodeBeforeStep(), tracker.getExpandedMacro(), replacements);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2006, 2007 QNX Software Systems and others.
|
* Copyright (c) 2006, 2008 QNX Software Systems 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
|
||||||
|
@ -152,13 +152,13 @@ public class PDOMMacro implements IIndexMacro, IASTFileLocation {
|
||||||
try {
|
try {
|
||||||
byte style= pdom.getDB().getByte(record + MACRO_STYLE);
|
byte style= pdom.getDB().getByte(record + MACRO_STYLE);
|
||||||
if (style == MACROSTYLE_FUNCTION) {
|
if (style == MACROSTYLE_FUNCTION) {
|
||||||
List paramList = new ArrayList();
|
List<char[]> paramList = new ArrayList<char[]>();
|
||||||
PDOMMacroParameter param= getFirstParameter();
|
PDOMMacroParameter param= getFirstParameter();
|
||||||
while (param != null) {
|
while (param != null) {
|
||||||
paramList.add(param.getName().getChars());
|
paramList.add(param.getName().getChars());
|
||||||
param = param.getNextParameter();
|
param = param.getNextParameter();
|
||||||
}
|
}
|
||||||
fParameterList= (char[][])paramList.toArray(new char[paramList.size()][]);
|
fParameterList= paramList.toArray(new char[paramList.size()][]);
|
||||||
}
|
}
|
||||||
} catch (CoreException e) {
|
} catch (CoreException e) {
|
||||||
CCorePlugin.log(e);
|
CCorePlugin.log(e);
|
||||||
|
@ -285,6 +285,7 @@ public class PDOMMacro implements IIndexMacro, IASTFileLocation {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public Object getAdapter(Class adapter) {
|
public Object getAdapter(Class adapter) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue