diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/ExpansionExplorerTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/ExpansionExplorerTests.java new file mode 100644 index 00000000000..5d9868ee808 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/ExpansionExplorerTests.java @@ -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); + } + + + +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LocationMapTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LocationMapTests.java index 68a700770db..08e4c6faf87 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LocationMapTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LocationMapTests.java @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -464,17 +464,18 @@ public class LocationMapTests extends BaseTestCase { fLocationMap.encounteredComment(12, 23, false); 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); - 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); 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)); - - 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)); + checkName(refs[0], macro2, "n2", macro3ref, IASTTranslationUnit.EXPANSION_NAME, ROLE_REFERENCE, FN, 110, 15, 2, 2, new String(LONGDIGITS, 110, 15)); } public void testContexts() { diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorBugsTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorBugsTests.java index a16d044ad2a..65c9db08c35 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorBugsTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorBugsTests.java @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -11,9 +11,6 @@ *******************************************************************************/ package org.eclipse.cdt.core.parser.tests.scanner; -import java.util.Iterator; -import java.util.List; - import junit.framework.TestSuite; import org.eclipse.cdt.core.parser.IProblem; diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorTests.java index ca6ef20302c..6b9249cdd4b 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorTests.java @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -286,6 +286,69 @@ public class PreprocessorTests extends PreprocessorTestsBase { 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 // str(); 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(); 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 initializeScanner(sb.toString()); - validateIdentifier("g"); + validateIdentifier("f"); validateToken(IToken.tLPAREN); validateInteger("2"); validateToken(IToken.tSTAR); @@ -849,7 +912,7 @@ public class PreprocessorTests extends PreprocessorTestsBase { validateIdentifier("f"); validateToken(IToken.tLPAREN); validateInteger("2"); - validateToken(IToken.tLPAREN); + validateToken(IToken.tSTAR); validateToken(IToken.tLPAREN); validateInteger("0"); validateToken(IToken.tCOMMA); diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/ScannerTestSuite.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/ScannerTestSuite.java index 26df045ebb0..290588438d6 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/ScannerTestSuite.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/ScannerTestSuite.java @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -23,6 +23,7 @@ public class ScannerTestSuite extends TestSuite { suite.addTest(PreprocessorTests.suite()); suite.addTest(InclusionTests.suite()); suite.addTest(PreprocessorBugsTests.suite()); + suite.addTest(ExpansionExplorerTests.suite()); return suite; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IPDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IPDOM.java deleted file mode 100644 index d198ea46738..00000000000 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IPDOM.java +++ /dev/null @@ -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 {} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTMacroExpansion.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTMacroExpansion.java index 0500a5e9cab..a650c2c3fee 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTMacroExpansion.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTMacroExpansion.java @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -27,6 +27,12 @@ public interface IASTMacroExpansion extends IASTNodeLocation { */ 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 * nodes within the same macro-expansion. However, it does not serve as an offset diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java index cf37fc7b365..9fe999998d0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -115,18 +115,9 @@ public interface IASTTranslationUnit extends IASTNode, IAdaptable { * @return List of IASTName nodes representing uses of the binding */ public IASTName[] getReferences(IBinding binding); - - /** - * 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. - * @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. + * Select the node in the treat that best fits the offset/length/file path. * * @param path - file name specified through path * @param offset - location in the file as an offset diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/rewrite/MacroExpansionExplorer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/rewrite/MacroExpansionExplorer.java new file mode 100644 index 00000000000..fa07e1b34a8 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/rewrite/MacroExpansionExplorer.java @@ -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 null 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; +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CharArrayMap.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CharArrayMap.java index 55546f4bf16..ab9c00981f5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CharArrayMap.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CharArrayMap.java @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,9 +10,11 @@ *******************************************************************************/ package org.eclipse.cdt.core.parser.util; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.Set; /** @@ -174,6 +176,15 @@ public final class CharArrayMap implements ICharArrayMap { return map.values(); } + public Collection keys() { + Set keys= map.keySet(); + ArrayList r= new ArrayList(keys.size()); + for (Key key : keys) { + r.add(CharArrayUtils.extract(key.buffer, key.start, key.length)); + } + return r; + } + public void clear() { map.clear(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTTranslationUnit.java index 27ec23fa710..fe529e88cfe 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTTranslationUnit.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTTranslationUnit.java @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * 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 { 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 IASTPreprocessorIncludeStatement[] EMPTY_PREPROCESSOR_INCLUSION_ARRAY = new IASTPreprocessorIncludeStatement[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); } - /* - * (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 { { shouldVisitNames = true; @@ -546,6 +533,7 @@ public class CASTTranslationUnit extends CASTNode implements IASTTranslationUnit return new IASTComment[0]; } + @SuppressWarnings("unchecked") public Object getAdapter(Class adapter) { if (adapter.isAssignableFrom(resolver.getClass())) { return resolver; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java index 247e1714c3c..257f6a96438 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * 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 { 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 IASTPreprocessorIncludeStatement[] EMPTY_PREPROCESSOR_INCLUSION_ARRAY = new IASTPreprocessorIncludeStatement[0]; 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); } - - 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 { { shouldVisitNames = true; @@ -512,6 +504,7 @@ public class CPPASTTranslationUnit extends CPPASTNode implements ICPPASTTranslat return new IASTComment[0]; } + @SuppressWarnings("unchecked") public Object getAdapter(Class adapter) { if (adapter.isAssignableFrom(resolver.getClass())) { return resolver; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorName.java index 4c2afd1b275..59198c3b1af 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorName.java @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -124,10 +124,12 @@ class ASTMacroReferenceName extends ASTPreprocessorName { fImageLocationInfo= imgLocationInfo; } + @Override public boolean isReference() { return true; } + @Override public IASTImageLocation getImageLocation() { if (fImageLocationInfo != null) { IASTTranslationUnit tu= getTranslationUnit(); @@ -140,5 +142,5 @@ class ASTMacroReferenceName extends ASTPreprocessorName { return null; } return super.getImageLocation(); - } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java index 0a27cf07b21..4e54f2961dc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java @@ -467,6 +467,10 @@ class ASTFileLocation implements IASTFileLocation { public int getSequenceEndNumber() { return fLocationCtx.getSequenceNumberForOffset(fOffset+fLength, true); } + + public LocationCtxFile getLocationContext() { + return fLocationCtx; + } } class ASTMacroExpansionLocation implements IASTMacroExpansion { @@ -489,6 +493,10 @@ class ASTMacroExpansionLocation implements IASTMacroExpansion { public IASTPreprocessorMacroDefinition getMacroDefinition() { return fContext.getMacroDefinition(); } + + public IASTName getMacroReference() { + return fContext.getMacroReference(); + } public IASTFileLocation asFileLocation() { return ((LocationCtxContainer) fContext.getParent()).createFileLocation(fContext.fOffsetInParent, fContext.fEndOffsetInParent-fContext.fOffsetInParent); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java index f9a6baf3b69..74dc2ff4a4f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java @@ -14,7 +14,9 @@ package org.eclipse.cdt.internal.core.parser.scanner; import java.io.File; import java.io.IOException; +import java.text.DateFormatSymbols; import java.util.Calendar; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; 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.ParserLanguage; 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.internal.core.parser.scanner.ExpressionEvaluator.EvalException; import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions; 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 * you should be using the {@link IScanner} interface. * @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 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 tNOSPACE= IToken.FIRST_RESERVED_PREPROCESSOR+4; 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_VERSION__ = new ObjectStyleMacro("__STDC_VERSION_".toCharArray(), "199901L".toCharArray()); //$NON-NLS-1$ //$NON-NLS-2$ + private interface IIncludeFileTester { Object checkFile(String path, String fileName); } @@ -120,7 +123,8 @@ public class CPreprocessor implements ILexerLog, IScanner { public Token execute() { StringBuffer buffer = new StringBuffer("\""); //$NON-NLS-1$ 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$ append(buffer, cal.get(Calendar.DAY_OF_MONTH)); buffer.append(" "); //$NON-NLS-1$ @@ -140,7 +144,7 @@ public class CPreprocessor implements ILexerLog, IScanner { public Token execute() { StringBuffer buffer = new StringBuffer("\""); //$NON-NLS-1$ Calendar cal = Calendar.getInstance(); - append(buffer, cal.get(Calendar.HOUR)); + append(buffer, cal.get(Calendar.HOUR_OF_DAY)); buffer.append(":"); //$NON-NLS-1$ append(buffer, cal.get(Calendar.MINUTE)); buffer.append(":"); //$NON-NLS-1$ @@ -176,7 +180,7 @@ public class CPreprocessor implements ILexerLog, IScanner { private boolean fHandledCompletion= false; // state information - private final CharArrayObjectMap fMacroDictionary = new CharArrayObjectMap(512); + private final CharArrayMap fMacroDictionary = new CharArrayMap(512); private final LocationMap fLocationMap = new LocationMap(); /** Set of already included files */ @@ -345,9 +349,9 @@ public class CPreprocessor implements ILexerLog, IScanner { } } - Object[] predefined= fMacroDictionary.valueArray(); - for (int i = 0; i < predefined.length; i++) { - fLocationMap.registerPredefinedMacro((PreprocessorMacro) predefined[i]); + Collection predefined= fMacroDictionary.values(); + for (PreprocessorMacro macro : predefined) { + fLocationMap.registerPredefinedMacro(macro); } } @@ -413,13 +417,10 @@ public class CPreprocessor implements ILexerLog, IScanner { } public Map getMacroDefinitions() { - final CharArrayObjectMap objMap= fMacroDictionary; - int size = objMap.size(); - Map hashMap = new HashMap(size); - for (int i = 0; i < size; i++) { - hashMap.put(String.valueOf(objMap.keyAt(i)), (IMacroBinding) objMap.getAt(i)); - } - + Map hashMap = new HashMap(fMacroDictionary.size()); + for (char[] key : fMacroDictionary.keys()) { + hashMap.put(String.valueOf(key), fMacroDictionary.get(key)); + } return hashMap; } @@ -1165,7 +1166,7 @@ public class CPreprocessor implements ILexerLog, IScanner { lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); final int endOffset= lexer.currentToken().getEndOffset(); 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); } @@ -1392,7 +1393,7 @@ public class CPreprocessor implements ILexerLog, IScanner { */ private boolean expandMacro(final Token identifier, Lexer lexer, boolean stopAtNewline) throws OffsetLimitReachedException { final char[] name= identifier.getCharImage(); - PreprocessorMacro macro= (PreprocessorMacro) fMacroDictionary.get(name); + PreprocessorMacro macro= fMacroDictionary.get(name); if (macro == null) { return false; } @@ -1419,4 +1420,12 @@ public class CPreprocessor implements ILexerLog, IScanner { fCurrentContext= new ScannerContext(ctx, fCurrentContext, replacement); return true; } + + @SuppressWarnings("unchecked") + public Object getAdapter(Class adapter) { + if (adapter.isAssignableFrom(fMacroExpander.getClass())) { + return fMacroExpander; + } + return null; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ExpressionEvaluator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ExpressionEvaluator.java index 7a9063aeebc..0da348357f3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ExpressionEvaluator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ExpressionEvaluator.java @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * 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.IToken; -import org.eclipse.cdt.core.parser.util.CharArrayObjectMap; +import org.eclipse.cdt.core.parser.util.CharArrayMap; /** * Used to evaluate expressions in preprocessor directives. @@ -40,11 +40,11 @@ class ExpressionEvaluator { } private Token fTokens; - private CharArrayObjectMap fDictionary; + private CharArrayMap fDictionary; - public boolean evaluate(TokenList condition, CharArrayObjectMap dictionary) throws EvalException { + public boolean evaluate(TokenList condition, CharArrayMap macroDictionary) throws EvalException { fTokens= condition.first(); - fDictionary= dictionary; + fDictionary= macroDictionary; return expression() != 0; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationResolver.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationResolver.java index a335791b57a..13049444d49 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationResolver.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationResolver.java @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * 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.IASTFileLocation; 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.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; @@ -103,9 +104,12 @@ public interface ILocationResolver { */ 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); /** @@ -122,7 +126,7 @@ public interface ILocationResolver { int getSequenceNumberForFileOffset(String filePath, int fileOffset); /** - * @see IASTTranslationUnit#getUnpreprocessedSignature(IASTFileLocation). + * @see IASTNode#getRawSignature(). */ 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. */ 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); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtx.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtx.java index df3e204c95a..97ec22d0369 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtx.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtx.java @@ -14,7 +14,6 @@ import java.util.ArrayList; import java.util.Collection; 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.IASTTranslationUnit.IDependencyTree.IASTInclusionNode; @@ -103,14 +102,14 @@ abstract class LocationCtx implements ILocationCtx { * Returns the minimal file location containing the specified sequence number range, assuming * 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); } /** * 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); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxContainer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxContainer.java index 32c4af4daa9..d67bb91168b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxContainer.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxContainer.java @@ -40,6 +40,7 @@ class LocationCtxContainer extends LocationCtx { fSource= source; } + @Override public Collection getChildren() { if (fChildren == null) { return Collections.emptyList(); @@ -84,10 +85,12 @@ class LocationCtxContainer extends LocationCtx { return result; } + @Override public void addChildSequenceLength(int childLength) { fChildSequenceLength+= childLength; } + @Override public final LocationCtx findSurroundingContext(int sequenceNumber, int length) { int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber; final LocationCtx child= findChildLessOrEqualThan(sequenceNumber, false); @@ -97,6 +100,7 @@ class LocationCtxContainer extends LocationCtx { return this; } + @Override public final LocationCtxMacroExpansion findSurroundingMacroExpansion(int sequenceNumber, int length) { int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber; final LocationCtx child= findChildLessOrEqualThan(sequenceNumber, true); @@ -106,7 +110,8 @@ class LocationCtxContainer extends LocationCtx { return null; } - public IASTFileLocation findMappedFileLocation(int sequenceNumber, int length) { + @Override + public ASTFileLocation findMappedFileLocation(int sequenceNumber, int length) { // try to delegate to a child. int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber; final LocationCtx child= findChildLessOrEqualThan(sequenceNumber, false); @@ -198,6 +203,7 @@ class LocationCtxContainer extends LocationCtx { return idx >= 0 ? fChildren.get(idx) : null; } + @Override public void getInclusions(ArrayList result) { if (fChildren != null) { for (Iterator iterator = fChildren.iterator(); iterator.hasNext();) { @@ -212,6 +218,7 @@ class LocationCtxContainer extends LocationCtx { } } + @Override public int getLineNumber(int offset) { if (fLineOffsets == null) { fLineOffsets= computeLineOffsets(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxFile.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxFile.java index 2ea099d04a4..0963ddadde0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxFile.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxFile.java @@ -10,7 +10,10 @@ *******************************************************************************/ 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. @@ -26,15 +29,18 @@ class LocationCtxFile extends LocationCtxContainer { fASTInclude= inclusionStatement; } + @Override public final void addChildSequenceLength(int childLength) { super.addChildSequenceLength(childLength); } + @Override public final String getFilePath() { return fFilename; } - public IASTFileLocation findMappedFileLocation(int sequenceNumber, int length) { + @Override + public ASTFileLocation findMappedFileLocation(int sequenceNumber, int length) { // try to delegate to a child. final int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber; final int sequenceEnd= sequenceNumber+length; @@ -76,14 +82,17 @@ class LocationCtxFile extends LocationCtxContainer { 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); } + @Override public ASTInclusionStatement getInclusionStatement() { return fASTInclude; } + @Override ASTFileLocation createFileLocation(int start, int length) { return new ASTFileLocation(this, start, length); } @@ -95,4 +104,20 @@ class LocationCtxFile extends LocationCtxContainer { } return sequenceNumber >= child.fSequenceNumber + child.getSequenceLength(); } + + public void collectExplicitMacroExpansions(int offset, int length, ArrayList result) { + Collection 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())); + } + } + } + } } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java index 81fbce6a917..6e6b307f647 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java @@ -19,6 +19,7 @@ import java.util.List; import org.eclipse.cdt.core.dom.ast.IASTComment; import org.eclipse.cdt.core.dom.ast.IASTFileLocation; 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.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; @@ -48,7 +49,7 @@ public class LocationMap implements ILocationResolver { private ArrayList fProblems= new ArrayList(); private ArrayList fComments= new ArrayList(); private ArrayList fBuiltinMacros= new ArrayList(); - private IdentityHashMap> fMacroReferences= new IdentityHashMap>(); + private ArrayList fMacroReferences= new ArrayList(); private LocationCtxFile fRootContext= null; private LocationCtx fCurrentContext= null; @@ -157,27 +158,22 @@ public class LocationMap implements ILocationResolver { int endNumber= getSequenceNumberForOffset(endOffset); final int length= endNumber-nameNumber; + ASTMacroReferenceName expansion= new ASTMacroReferenceName(fTranslationUnit, nameNumber, nameEndNumber, macro, null); for (int i = 0; i < implicitMacroReferences.length; i++) { ASTMacroReferenceName name = (ASTMacroReferenceName) implicitMacroReferences[i]; name.setOffsetAndLength(nameNumber, length); - addMacroReference((IMacroBinding) name.getBinding(), name); + name.setParent(expansion); + addMacroReference(name); } - - ASTMacroReferenceName expansion= new ASTMacroReferenceName(fTranslationUnit, nameNumber, nameEndNumber, macro, null); - addMacroReference(macro, expansion); + addMacroReference(expansion); fCurrentContext= new LocationCtxMacroExpansion(this, (LocationCtxContainer) fCurrentContext, nameOffset, endOffset, endNumber, contextLength, imageLocations, expansion); fLastChildInsertionOffset= 0; return fCurrentContext; } - private void addMacroReference(IMacroBinding macro, IASTName name) { - List list= fMacroReferences.get(macro); - if (list == null) { - list= new ArrayList(); - fMacroReferences.put(macro, list); - } - list.add(name); + private void addMacroReference(IASTName name) { + fMacroReferences.add(name); } /** @@ -310,7 +306,7 @@ public class LocationMap implements ILocationResolver { // not using endOffset, compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset); final ASTUndef undef = new ASTUndef(fTranslationUnit, name, startOffset, nameOffset, nameEndOffset, definition); fDirectives.add(undef); - addMacroReference(definition, undef.getMacroName()); + addMacroReference(undef.getMacroName()); } public void setRootNode(IASTTranslationUnit root) { @@ -351,15 +347,54 @@ public class LocationMap implements ILocationResolver { return new String(ctx.getFilePath()); } - public IASTFileLocation getMappedFileLocation(int sequenceNumber, int length) { + public ASTFileLocation getMappedFileLocation(int sequenceNumber, int length) { return fRootContext.findMappedFileLocation(sequenceNumber, length); } public char[] getUnpreprocessedSignature(IASTFileLocation loc) { - if (loc instanceof ASTFileLocation) { - return ((ASTFileLocation) loc).getSource(); - } - return CharArrayUtils.EMPTY; + ASTFileLocation floc= convertFileLocation(loc); + if (floc == null) { + 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 list= new ArrayList(); + + 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) { @@ -538,13 +573,25 @@ public class LocationMap implements ILocationResolver { } public IASTName[] getReferences(IMacroBinding binding) { - List list= fMacroReferences.get(binding); - if (list == null) { - return EMPTY_NAMES; + List result= new ArrayList(); + for (IASTName name : fMacroReferences) { + 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 result= new ArrayList(); + for (IASTName name : fMacroReferences) { + if (name.getParent() == ref) { + result.add(name); + } + } + return result.toArray(new IASTName[result.size()]); + } + public IDependencyTree getDependencyTree() { return new DependencyTree(fRootContext); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpander.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpander.java index 6aef6aded7a..99b9b3af247 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpander.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpander.java @@ -11,13 +11,14 @@ package org.eclipse.cdt.internal.core.parser.scanner; import java.util.ArrayList; +import java.util.BitSet; import java.util.IdentityHashMap; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.parser.IProblem; import org.eclipse.cdt.core.parser.IToken; 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.internal.core.parser.scanner.ImageLocationInfo.MacroImageLocationInfo; import org.eclipse.cdt.internal.core.parser.scanner.ImageLocationInfo.ParameterImageLocationInfo; @@ -31,7 +32,8 @@ import org.eclipse.cdt.internal.core.parser.scanner.MacroDefinitionParser.TokenP public class MacroExpander { 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 TokenList EMPTY_TOKEN_LIST = new TokenList(); + /** * Marks the beginning and the end of the scope of a macro expansion. Necessary to properly * handle recursive expansions and to figure out whether spaces are required during a stringify @@ -125,7 +127,7 @@ public class MacroExpander { private final ILexerLog fLog; private final MacroDefinitionParser fDefinitionParser; - private final CharArrayObjectMap fDictionary; + private final CharArrayMap fDictionary; private final LocationMap fLocationMap; private final LexerOptions fLexOptions; private ArrayList fImplicitMacroExpansions= new ArrayList(); @@ -133,9 +135,9 @@ public class MacroExpander { private boolean fCompletionMode; private int fStartOffset; private int fEndOffset; - - public MacroExpander(ILexerLog log, CharArrayObjectMap dict, LocationMap locationMap, LexerOptions lexOptions) { - fDictionary= dict; + + public MacroExpander(ILexerLog log, CharArrayMap macroDictionary, LocationMap locationMap, LexerOptions lexOptions) { + fDictionary= macroDictionary; fLocationMap= locationMap; fDefinitionParser= new MacroDefinitionParser(); fLexOptions= lexOptions; @@ -158,45 +160,144 @@ public class MacroExpander { // setup input sequence TokenSource input= new TokenSource(lexer, stopAtNewline); TokenList firstExpansion= new TokenList(); - expandOne(identifier, macro, forbidden, input, firstExpansion); + expandOne(identifier, macro, forbidden, input, firstExpansion, null); input.prepend(firstExpansion); - TokenList result= expandAll(input, forbidden); + TokenList result= expandAll(input, forbidden, null); postProcessTokens(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 forbidden= new IdentityHashMap(); + + // 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 * tokens from the input (to read the parameters) and stores the resulting tokens together * with boundary markers in the result token list. * Returns the last token of the expansion. */ - private Token expandOne(Token lastConsumed, PreprocessorMacro macro, IdentityHashMap forbidden, TokenSource input, TokenList result) + private Token expandOne(Token lastConsumed, PreprocessorMacro macro, + IdentityHashMap forbidden, TokenSource input, TokenList result, + MacroExpansionTracker tracker) throws OffsetLimitReachedException { result.append(new ExpansionBoundary(macro, true)); if (macro.isFunctionStyle()) { - final TokenSource[] argInputs= new TokenSource[macro.getParameterPlaceholderList().length]; - lastConsumed= parseArguments(input, (FunctionStyleMacro) macro, forbidden, argInputs); - TokenList[] clonedArgs= new TokenList[argInputs.length]; - TokenList[] expandedArgs= new TokenList[argInputs.length]; - for (int i = 0; i < argInputs.length; i++) { - final TokenSource argInput = argInputs[i]; - clonedArgs[i]= argInput.cloneTokens(); - final TokenList expandedArg= expandAll(argInput, forbidden); - expandedArgs[i]= expandedArg; + final int paramCount = macro.getParameterPlaceholderList().length; + final TokenSource[] argInputs= new TokenSource[paramCount]; + final BitSet paramUsage= getParamUsage(macro); + if (tracker != null) { + tracker.startFunctionStyleMacro((Token) lastConsumed.clone()); + } + lastConsumed= parseArguments(input, (FunctionStyleMacro) macro, forbidden, argInputs, tracker); + TokenList[] clonedArgs= new TokenList[paramCount]; + 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 { - 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)); return lastConsumed; } - private TokenList expandAll(TokenSource input, IdentityHashMap forbidden) throws OffsetLimitReachedException { + private void executeScopeMarkers(TokenSource input, IdentityHashMap 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 forbidden, + MacroExpansionTracker tracker) throws OffsetLimitReachedException { final TokenList result= new TokenList(); Token l= null; Token t= input.removeFirst(); @@ -207,9 +308,12 @@ public class MacroExpander { t= input.removeFirst(); // don't change l continue; 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 - if (macro == null || (macro.isFunctionStyle() && !input.findLParenthesis())) { + else if (macro == null || (macro.isFunctionStyle() && !input.findLParenthesis())) { result.append(t); } else if (forbidden.containsKey(macro)) { @@ -227,7 +331,7 @@ public class MacroExpander { TokenList replacement= new TokenList(); 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 input.prepend(replacement); @@ -262,12 +366,12 @@ public class MacroExpander { if (l != null && t != null) { final Object s1= l.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()) { target.append(new Token(CPreprocessor.tNOSPACE, null, 0, 0)); } 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. * @param forbidden + * @param tracker * @throws OffsetLimitReachedException */ - private Token parseArguments(TokenSource input, FunctionStyleMacro macro, IdentityHashMap forbidden, TokenSource[] result) throws OffsetLimitReachedException { + private Token parseArguments(TokenSource input, FunctionStyleMacro macro, IdentityHashMap forbidden, TokenSource[] result, + MacroExpansionTracker tracker) throws OffsetLimitReachedException { final int argCount= macro.getParameterPlaceholderList().length; final boolean hasVarargs= macro.hasVarArgs() != FunctionStyleMacro.NO_VAARGS; final int requiredArgs= hasVarargs ? argCount-1 : argCount; @@ -296,6 +402,17 @@ public class MacroExpander { Token t= input.fetchFirst(); if (t == null) { 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; switch(t.getType()) { @@ -414,7 +531,7 @@ public class MacroExpander { case IToken.tPOUND: addSpacemarker(l, t, result); // start stringify - StringBuffer buf= new StringBuffer(); + StringBuilder buf= new StringBuilder(); buf.append('"'); if (n != null && n.getType() == CPreprocessor.tMACRO_PARAMETER) { idx= ((TokenParameterReference) n).getIndex(); @@ -441,65 +558,65 @@ public class MacroExpander { break; case IToken.tPOUNDPOUND: - if (pasteArg1 != null) { - Token pasteArg2= null; - TokenList rest= null; - if (n != null) { - if (n.getType() == CPreprocessor.tMACRO_PARAMETER) { - idx= ((TokenParameterReference) n).getIndex(); - if (idx < args.length) { // be defensive - TokenList arg= clone(args[idx]); - pasteArg2= arg.first(); - - // gcc-extension - if (idx == args.length-1 && macro.hasVarArgs() != FunctionStyleMacro.NO_VAARGS) { - if (pasteArg1.getType() == IToken.tCOMMA) { // no paste operation - if (arg.first() != null) { - result.append(pasteArg1); - rest= arg; - } - pasteArg1= pasteArg2= null; - } + Token pasteArg2= null; + TokenList rest= null; + if (n != null) { + if (n.getType() == CPreprocessor.tMACRO_PARAMETER) { + TokenList arg; + idx= ((TokenParameterReference) n).getIndex(); + if (idx < args.length) { // be defensive + // gcc-extension + if (idx == args.length-1 && macro.hasVarArgs() != FunctionStyleMacro.NO_VAARGS && + pasteArg1 != null && pasteArg1.getType() == IToken.tCOMMA) { // no paste operation + arg= clone(expandedArgs[idx]); + if (arg.first() != null) { + result.append(pasteArg1); + rest= arg; } + pasteArg1= pasteArg2= null; + } + else { + arg= clone(args[idx]); + pasteArg2= arg.first(); if (pasteArg2 != null && arg.first() != arg.last()) { rest= arg; 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; + } + else { + idx= -1; + pasteArg2= n; + } + t= n; + n= (Token) n.getNext(); + pasteNext= n != null && n.getType() == IToken.tPOUNDPOUND; - 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 + generated= tokenpaste(pasteArg1, pasteArg2, macro); + pasteArg1= null; + + 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) { + if (pasteNext) { + pasteArg1= rest.last(); + if (pasteArg1 != null) { + result.appendAllButLast(rest); + addSpacemarker(result.last(), pasteArg1, result); // start token paste } } - if (rest != null) { - if (pasteNext) { - pasteArg1= rest.last(); - if (pasteArg1 != null) { - 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 - } + 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) { TokenList replacement= clone(macro.getTokens(fDefinitionParser, fLexOptions)); @@ -574,6 +738,9 @@ public class MacroExpander { } private Token tokenpaste(Token arg1, Token arg2, PreprocessorMacro macro) { + if (arg1 == null) { + return arg2; + } if (arg2 == null) { return arg1; } @@ -598,7 +765,7 @@ public class MacroExpander { return null; } - private void stringify(TokenList tokenList, StringBuffer buf) { + private void stringify(TokenList tokenList, StringBuilder buf) { Token t= tokenList.first(); if (t == null) { return; @@ -608,8 +775,7 @@ public class MacroExpander { boolean space= false; for (; t != null; l=t, t=n) { n= (Token) t.getNext(); - if (!space && l != null && l.fSource != null && l.fSource == t.fSource && - l.getEndOffset() != t.getOffset()) { + if (!space && hasImplicitSpace(l, t)) { buf.append(' '); space= true; } @@ -695,4 +861,10 @@ public class MacroExpander { 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; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpansionStep.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpansionStep.java new file mode 100644 index 00000000000..9796d2e10be --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpansionStep.java @@ -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; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpansionTracker.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpansionTracker.java new file mode 100644 index 00000000000..7eeeb2434d2 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpansionTracker.java @@ -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 fArguments= new ArrayList(); + + 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 fMacroStack= new LinkedList(); + + 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 null 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++; + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MultiMacroExpansionExplorer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MultiMacroExpansionExplorer.java new file mode 100644 index 00000000000..cbb0d900eb6 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MultiMacroExpansionExplorer.java @@ -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 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 combineReplaceEdits(int count) { + ArrayList edits= new ArrayList(); + 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 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 replacements= new ArrayList(); + 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); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/SingleMacroExpansionExplorer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/SingleMacroExpansionExplorer.java new file mode 100644 index 00000000000..f5004cb278e --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/SingleMacroExpansionExplorer.java @@ -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 fDictionary; + private MacroExpansionStep fFullExpansion; + private int fExpansionCount; + + public SingleMacroExpansionExplorer(String input, IASTName ref, IASTName[] implicitRefs) { + fInput= input; + fDictionary= createDictionary(ref, implicitRefs); + } + + private CharArrayMap createDictionary(IASTName ref, IASTName[] implicitRefs) { + // mstodo handle dynamic style macros + // mstodo clone index-macros + CharArrayMap map= new CharArrayMap(implicitRefs.length+1); + addMacroDefinition(map, ref); + for (IASTName name : implicitRefs) { + addMacroDefinition(map, name); + } + return map; + } + + private void addMacroDefinition(CharArrayMap 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); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMMacro.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMMacro.java index 5df83345fb8..231341e9bbd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMMacro.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMMacro.java @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -152,13 +152,13 @@ public class PDOMMacro implements IIndexMacro, IASTFileLocation { try { byte style= pdom.getDB().getByte(record + MACRO_STYLE); if (style == MACROSTYLE_FUNCTION) { - List paramList = new ArrayList(); + List paramList = new ArrayList(); PDOMMacroParameter param= getFirstParameter(); while (param != null) { paramList.add(param.getName().getChars()); param = param.getNextParameter(); } - fParameterList= (char[][])paramList.toArray(new char[paramList.size()][]); + fParameterList= paramList.toArray(new char[paramList.size()][]); } } catch (CoreException e) { CCorePlugin.log(e); @@ -285,6 +285,7 @@ public class PDOMMacro implements IIndexMacro, IASTFileLocation { return null; } + @SuppressWarnings("unchecked") public Object getAdapter(Class adapter) { return null; }