diff --git a/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/AllCoreTests.java b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/AllCoreTests.java index 7d1d2e5bb28..f4c36c309be 100644 --- a/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/AllCoreTests.java +++ b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/AllCoreTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 QNX Software Systems and others. + * Copyright (c) 2000, 2009 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,6 +7,7 @@ * * Contributors: * QNX Software Systems - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.model.tests; @@ -42,6 +43,7 @@ public class AllCoreTests { suite.addTest(CModelElementsTests.suite()); suite.addTest(CModelIdentifierTests.suite()); suite.addTest(CModelExceptionTest.suite()); + suite.addTest(CModelBuilderInactiveCodeTest.suite()); suite.addTest(FlagTests.suite()); suite.addTest(ArchiveTests.suite()); suite.addTest(TranslationUnitTests.suite()); diff --git a/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/CModelBuilderInactiveCodeTest.java b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/CModelBuilderInactiveCodeTest.java new file mode 100644 index 00000000000..d6f77a46eeb --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/CModelBuilderInactiveCodeTest.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2009 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 (Wind River Systems) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.core.model.tests; + +import junit.framework.Test; + +import org.eclipse.cdt.core.dom.IPDOMManager; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.IInclude; +import org.eclipse.cdt.core.model.IMacro; +import org.eclipse.cdt.core.model.ISourceReference; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.core.testplugin.CProjectHelper; +import org.eclipse.cdt.core.testplugin.CTestPlugin; +import org.eclipse.cdt.core.testplugin.util.BaseTestCase; + +/** + * Tests for C model inactive code parsing. + */ +public class CModelBuilderInactiveCodeTest extends BaseTestCase { + + public static Test suite() { + return suite(CModelBuilderInactiveCodeTest.class, "_"); + } + + private ICProject fCProject; + private ITranslationUnit fTU; + + public CModelBuilderInactiveCodeTest(String name) { + super(name); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + fCProject= CProjectHelper.createCProject(getName(), null, IPDOMManager.ID_FAST_INDEXER); + assertNotNull(fCProject); + CProjectHelper.importSourcesFromPlugin(fCProject, CTestPlugin.getDefault().getBundle(), "/resources/cmodel"); + fTU= (ITranslationUnit) CProjectHelper.findElement(fCProject, "CModelBuilderInactiveCodeTest.cpp"); + assertNotNull(fTU); + } + + @Override + protected void tearDown() throws Exception { + CProjectHelper.delete(fCProject); + super.tearDown(); + } + + public void testPreprocessorNodes() throws Exception { + ISourceReference e= (ISourceReference) fTU.getElement("include"); + assertTrue(e instanceof IInclude); + assertFalse(e.isActive()); + + e= (ISourceReference) fTU.getElement("MACRO1"); + assertTrue(e instanceof IMacro); + assertFalse(e.isActive()); + + e= (ISourceReference) fTU.getElement("MACRO2"); + assertTrue(e instanceof IMacro); + assertFalse(e.isActive()); + } +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/InactiveCodeTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/InactiveCodeTests.java new file mode 100644 index 00000000000..540dfdcd605 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/InactiveCodeTests.java @@ -0,0 +1,257 @@ +/******************************************************************************* + * Copyright (c) 2009 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.parser.IToken; + + +/** + * Tests for using the preprocessor on inactive code + */ +public class InactiveCodeTests extends PreprocessorTestsBase { + + public static TestSuite suite() { + return suite(InactiveCodeTests.class); + } + + @Override + protected void initializeScanner() throws Exception { + super.initializeScanner(); + fScanner.setProcessInactiveCode(true); + } + + private void validate(char[] activeInactive) throws Exception { + boolean active= true; + for (char c : activeInactive) { + switch(c) { + case 'a': + if (!active) { + validateToken(IToken.tINACTIVE_CODE_END); + active= true; + } + validateIdentifier("a"); + break; + case 'i': + validateToken(active ? IToken.tINACTIVE_CODE_START : IToken.tINACTIVE_CODE_SEPARATOR); + active= false; + validateIdentifier("i"); + break; + default: + fail(); + } + } + } + + + // #define D + // #ifdef D + // a + // #elif 1 + // i + // #elif 0 + // i + // #else + // i + // #endif + // a + // #ifdef UD + // i + // #elif 1 + // a + // #elif 0 + // i + // #else + // i + // #endif + // a + // #ifdef UD + // i + // #elif 0 + // i + // #elif 1 + // a + // #else + // i + // #endif + // a + // #ifdef UD + // i + // #elif 0 + // i + // #else + // a + // #endif + public void testIfDef() throws Exception { + initializeScanner(); + validate("aiiiaiaiiaiiaiaiia".toCharArray()); + validateEOF(); + } + + // #define D + // #ifndef UD + // a + // #elif 1 + // i + // #elif 0 + // i + // #else + // i + // #endif + // a + // #ifndef D + // i + // #elif 1 + // a + // #elif 0 + // i + // #else + // i + // #endif + // a + // #ifndef D + // i + // #elif 0 + // i + // #elif 1 + // a + // #else + // i + // #endif + // a + // #ifndef D + // i + // #elif 0 + // i + // #else + // a + // #endif + public void testIfnDef() throws Exception { + initializeScanner(); + validate("aiiiaiaiiaiiaiaiia".toCharArray()); + validateEOF(); + } + + // #if 1 + // a + // #elif 1 + // i + // #elif 0 + // i + // #else + // i + // #endif + // a + // #if 0 + // i + // #elif 1 + // a + // #elif 0 + // i + // #else + // i + // #endif + // a + // #if 0 + // i + // #elif 0 + // i + // #elif 1 + // a + // #else + // i + // #endif + // a + // #if 0 + // i + // #elif 0 + // i + // #else + // a + // #endif + public void testIf() throws Exception { + initializeScanner(); + validate("aiiiaiaiiaiiaiaiia".toCharArray()); + validateEOF(); + } + + // #if 0 + // i + // #if 1 + // i + // #elif 0 + // i + // #else + // i + // #endif + // i + // #endif + // a + // #if 0 + // i + // #if 0 + // i + // #elif 1 + // i + // #else + // i + // #endif + // i + // #endif + // a + // #if 0 + // i + // #if 0 + // i + // #elif 0 + // i + // #else + // i + // #endif + // i + // #endif + // a + public void testNestedInInactive() throws Exception { + initializeScanner(); + validate("iiiiiaiiiiiaiiiiia".toCharArray()); + validateEOF(); + } + + // #if 0 + // i + // #define M + // #endif + // a + // #ifdef M + // i + // #endif + // a + public void testInactiveMacroDefinition() throws Exception { + initializeScanner(); + validate("iaia".toCharArray()); + validateEOF(); + assertNull(fScanner.getMacroDefinitions().get("M")); + } + + // #ifdef X + // # if 0 + // # endif + // #elif defined (Y) + // #endif + public void testDefinedSyntax() throws Exception { + initializeScanner(); + validateToken(IToken.tINACTIVE_CODE_START); + fScanner.skipInactiveCode(); + validateEOF(); + validateProblemCount(0); + } +} 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 ef05190e6ec..2cbd0948e17 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, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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 @@ -408,8 +408,8 @@ public class LocationMapTests extends BaseTestCase { final String[] params = new String[]{"p1", "p2"}; IMacroBinding macro2= new TestMacro("n2", "exp2", params); init(DIGITS); - fLocationMap.encounterPoundDefine(0, 0, 0, 0, 0, macro1); - fLocationMap.encounterPoundDefine(0, 1, 3, 10, 16, macro2); + fLocationMap.encounterPoundDefine(0, 0, 0, 0, 0, true, macro1); + fLocationMap.encounterPoundDefine(0, 1, 3, 10, 16, true, macro2); IASTPreprocessorMacroDefinition[] prep= fLocationMap.getMacroDefinitions(); assertEquals(2, prep.length); checkMacroDefinition(prep[0], macro1, "", "n1", "", "exp1", null, FN, 0, 0, 1, 0, 0); @@ -463,7 +463,7 @@ public class LocationMapTests extends BaseTestCase { assertEquals(2, fLocationMap.getCurrentLineNumber('\n'+1)); fLocationMap.registerPredefinedMacro(macro1); fLocationMap.registerMacroFromIndex(macro2, new Loc("ifile", 2, 12), 32); - fLocationMap.encounterPoundDefine(3, 13, 33, 63, 103, macro3); + fLocationMap.encounterPoundDefine(3, 13, 33, 63, 103, true, macro3); IASTName name1= fLocationMap.encounterImplicitMacroExpansion(macro1, null); IASTName name2= fLocationMap.encounterImplicitMacroExpansion(macro2, null); fLocationMap.pushMacroExpansion(110, 115, 125, 30, macro3, new IASTName[]{name1, name2}, new ImageLocationInfo[0]); 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 290588438d6..05de0774722 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, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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 @@ -24,6 +24,7 @@ public class ScannerTestSuite extends TestSuite { suite.addTest(InclusionTests.suite()); suite.addTest(PreprocessorBugsTests.suite()); suite.addTest(ExpansionExplorerTests.suite()); + suite.addTest(InactiveCodeTests.suite()); return suite; } } diff --git a/core/org.eclipse.cdt.core.tests/resources/cmodel/CModelBuilderInactiveCodeTest.cpp b/core/org.eclipse.cdt.core.tests/resources/cmodel/CModelBuilderInactiveCodeTest.cpp new file mode 100644 index 00000000000..a3f269294e9 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/resources/cmodel/CModelBuilderInactiveCodeTest.cpp @@ -0,0 +1,5 @@ +#if 0 +#include "include" +#define MACRO1 1 +#define MACRO2(x, y) x+y +#endif \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IInclude.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IInclude.java index 52a9b4bc67a..e5a9ee76d15 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IInclude.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IInclude.java @@ -37,12 +37,6 @@ public interface IInclude extends ICElement, ISourceReference, ISourceManipulati public boolean isLocal(); - /** - * @return whether this include directive is in active code, ie. not hidden - * by conditional compilation - */ - public boolean isActive(); - /** * @return whether this include directive was resolved and followed. */ diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ILanguage.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ILanguage.java index 7a17447690b..a8329ae56c0 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ILanguage.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ILanguage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2008 QNX Software Systems and others. + * Copyright (c) 2005, 2009 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -47,7 +47,7 @@ public interface ILanguage extends IAdaptable { /** * Option for {@link #getASTTranslationUnit(CodeReader, IScannerInfo, ICodeReaderFactory, IIndex, int, IParserLogService)} - * Performance optimization, instructs the parser not to create image-locations. + * Performance optimization, allows the parser not to create image-locations. * When using this option {@link IASTName#getImageLocation()} will always return null. */ public final static int OPTION_NO_IMAGE_LOCATIONS= 0x4; @@ -61,12 +61,21 @@ public interface ILanguage extends IAdaptable { /** * Option for {@link #getASTTranslationUnit(CodeReader, IScannerInfo, ICodeReaderFactory, IIndex, int, IParserLogService)} - * Instructs the parser not to create ast nodes for expressions within aggregate initializers + * Allows the parser not to create ast nodes for expressions within aggregate initializers * when they do not contain names. * @since 5.1 */ public final static int OPTION_SKIP_TRIVIAL_EXPRESSIONS_IN_AGGREGATE_INITIALIZERS= 0x10; + /** + * Option for {@link #getASTTranslationUnit(CodeReader, IScannerInfo, ICodeReaderFactory, IIndex, int, IParserLogService)} + * Instructs the parser to create ast nodes for inactive code branches, if possible. There is no guarantee that the ast + * can actually be created for the inactive parts. + * mstodo document how the ast can be accessed. + * @since 5.1 + */ + public final static int OPTION_PARSE_INACTIVE_CODE= 0x20; + /** * Return the language id for this language. * This is to differentiate languages from each other. diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ISourceReference.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ISourceReference.java index 6602afaae06..f721ca3a58e 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ISourceReference.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ISourceReference.java @@ -7,6 +7,7 @@ * * Contributors: * QNX Software Systems - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.model; @@ -56,4 +57,17 @@ public interface ISourceReference { * if this member is not declared in a translation unit (for example, a binary type). */ ITranslationUnit getTranslationUnit(); + + /** + * Returns whether this element is in active code. Code is inactive when it is hidden + * by conditional compilation. + * @since 5.1 + */ + public boolean isActive(); + + /** + * Allows to differentiate otherwise equal elements of the same file. + * @since 5.1 + */ + int getIndex(); } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java index 0b452099325..c84f0df79af 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 QNX Software Systems and others. + * Copyright (c) 2000, 2009 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -95,6 +95,14 @@ public interface ITranslationUnit extends ICElement, IParent, IOpenable, ISource */ public final static int AST_SKIP_TRIVIAL_EXPRESSIONS_IN_AGGREGATE_INITIALIZERS= 0x40; + /** + * Style constant for {@link #getAST(IIndex, int)}. + * Instructs the parser to make an attempt to create ast nodes for inactive code branches. + * mstodo document how to access those. + * @since 5.1 + */ + public final static int AST_PARSE_INACTIVE_CODE= 0x80; + /** * Creates and returns an include declaration in this translation unit * with the given name. @@ -167,9 +175,24 @@ public interface ITranslationUnit extends ICElement, IParent, IOpenable, ISource * @return the found shared working copy for this element, null if none * @see IBufferFactory * @since 2.0 + * @noreference This method is not intended to be referenced by clients. */ IWorkingCopy findSharedWorkingCopy(IBufferFactory bufferFactory); + /** + * Returns the shared working copy for this element, using the default IBuffer factory, or + * null, if no working copy has been created for this element. + *

+ * Users of this method must not destroy the resulting working copy. + * + * @param bufferFactory + * the given IBuffer factory + * @return the found shared working copy for this element, or null if none + * @see IBufferFactory + * @since 5.1 + */ + IWorkingCopy findSharedWorkingCopy(); + /** * Returns the contents of a translation unit as a char[] * @return char[] @@ -284,13 +307,11 @@ public interface ITranslationUnit extends ICElement, IParent, IOpenable, ISource * @see IBufferFactory * @see IProblemRequestor * @since 2.0 + * @noreference This method is not intended to be referenced by clients. */ + IWorkingCopy getSharedWorkingCopy(IProgressMonitor monitor, IBufferFactory factory) + throws CModelException; - IWorkingCopy getSharedWorkingCopy( - IProgressMonitor monitor, - IBufferFactory factory) - throws CModelException; - /** * Returns a shared working copy on this element using the given factory to create * the buffer, or this element if this element is already a working copy. @@ -333,9 +354,53 @@ public interface ITranslationUnit extends ICElement, IParent, IOpenable, ISource * @see IBufferFactory * @see IProblemRequestor * @since 2.0 + * @noreference This method is not intended to be referenced by clients. */ IWorkingCopy getSharedWorkingCopy(IProgressMonitor monitor, IBufferFactory factory, IProblemRequestor requestor) throws CModelException; + /** + * Returns a shared working copy on this element using the given factory to create the buffer, or this + * element if this element is already a working copy. This API can only answer an already existing working + * copy if it is based on the same original translation unit AND was using the same buffer factory (i.e. + * as defined by Object#equals). + *

+ * The life time of a shared working copy is as follows: + *

+ * So users of this method must destroy exactly once the working copy. + *

+ * Note that the buffer factory will be used for the life time of this working copy, i.e. if the working + * copy is closed then reopened, this factory will be used. The buffer will be automatically initialized + * with the original's compilation unit content upon creation. + *

+ * When the shared working copy instance is created, an ADDED ICElementDelta is reported on this working + * copy. + * + * @param monitor + * a progress monitor used to report progress while opening this compilation unit or + * null if no progress should be reported + * @param requestor + * a requestor which will get notified of problems detected during reconciling as they are + * discovered. The requestor can be set to null indicating that the client is not + * interested in problems. + * @exception CModelException + * if the contents of this element can not be determined. Reasons include: + *

+ * @return a shared working copy on this element using the given factory to create the buffer, or this + * element if this element is already a working copy + * @see IBufferFactory + * @see IProblemRequestor + * @since 5.1 + */ + IWorkingCopy getSharedWorkingCopy(IProgressMonitor monitor, IProblemRequestor requestor) throws CModelException; + /** * Returns the first using in this translation unit with the name * This is a handle-only method. The namespace declaration may or may not exist. @@ -409,7 +474,13 @@ public interface ITranslationUnit extends ICElement, IParent, IOpenable, ISource /** * Returns a new working copy for the Translation Unit. - * @return IWorkingCopy + * @since 5.1 + */ + IWorkingCopy getWorkingCopy(IProgressMonitor monitor) throws CModelException; + + /** + * Returns a new working copy for the Translation Unit. + * @noreference This method is not intended to be referenced by clients. */ IWorkingCopy getWorkingCopy(IProgressMonitor monitor, IBufferFactory factory) throws CModelException; diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ASTCache.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ASTCache.java index dd8abd76ed1..4ec9c6caa08 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ASTCache.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ASTCache.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. All rights reserved. + * Copyright (c) 2007, 2009 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 @@ -38,10 +38,15 @@ public class ASTCache { private static final String DEBUG_PREFIX= "[ASTCache] "; //$NON-NLS-1$ /** Full parse mode (no PDOM) */ - public static int PARSE_MODE_FULL= ITranslationUnit.AST_CONFIGURE_USING_SOURCE_CONTEXT; + public static int PARSE_MODE_FULL = ITranslationUnit.AST_CONFIGURE_USING_SOURCE_CONTEXT + | ITranslationUnit.AST_SKIP_TRIVIAL_EXPRESSIONS_IN_AGGREGATE_INITIALIZERS + | ITranslationUnit.AST_PARSE_INACTIVE_CODE; + /** Fast parse mode (use PDOM) */ - public static int PARSE_MODE_FAST= ITranslationUnit.AST_SKIP_ALL_HEADERS | ITranslationUnit.AST_CONFIGURE_USING_SOURCE_CONTEXT - | ITranslationUnit.AST_SKIP_TRIVIAL_EXPRESSIONS_IN_AGGREGATE_INITIALIZERS; + public static int PARSE_MODE_FAST = ITranslationUnit.AST_SKIP_ALL_HEADERS + | ITranslationUnit.AST_CONFIGURE_USING_SOURCE_CONTEXT + | ITranslationUnit.AST_SKIP_TRIVIAL_EXPRESSIONS_IN_AGGREGATE_INITIALIZERS + | ITranslationUnit.AST_PARSE_INACTIVE_CODE; /** * Do something with an AST. diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/BinaryElement.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/BinaryElement.java index ac86810b9d7..199919dab4f 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/BinaryElement.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/BinaryElement.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 QNX Software Systems and others. + * Copyright (c) 2000, 2009 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -245,4 +245,11 @@ public class BinaryElement extends CElement implements IBinaryElement, ISourceMa return 0; } + public boolean isActive() { + return true; + } + + public int getIndex() { + return 0; + } } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElement.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElement.java index ed4ae12ee6c..1718a5a10d2 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElement.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElement.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 QNX Software Systems and others. + * Copyright (c) 2000, 2009 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -279,6 +279,12 @@ public abstract class CElement extends PlatformObject implements ICElement { !lhsName.equals(rhsName)) { return false; } + + if (lhs instanceof ISourceReference && rhs instanceof ISourceReference) { + if (((ISourceReference) lhs).getIndex() != ((ISourceReference) rhs).getIndex()) { + return false; + } + } ICElement lhsParent= lhs.getParent(); ICElement rhsParent= rhs.getParent(); diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java index 0f796abe767..8857ea19dad 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java @@ -13,9 +13,8 @@ package org.eclipse.cdt.internal.core.model; import java.util.Collections; import java.util.Comparator; -import java.util.HashSet; +import java.util.HashMap; import java.util.List; -import java.util.Set; import java.util.Stack; import org.eclipse.cdt.core.CCorePlugin; @@ -74,6 +73,7 @@ import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.IContributedModelBuilder; import org.eclipse.cdt.core.model.INamespace; import org.eclipse.cdt.core.model.IProblemRequestor; +import org.eclipse.cdt.core.model.ISourceReference; import org.eclipse.cdt.core.model.IStructure; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.parser.Keywords; @@ -98,7 +98,7 @@ public class CModelBuilder2 implements IContributedModelBuilder { private ASTAccessVisibility fCurrentVisibility; private Stack fVisibilityStack; - private Set fAllNamespaces; + private HashMap fEqualElements; /** * Create a model builder for the given translation unit. @@ -132,11 +132,11 @@ public class CModelBuilder2 implements IContributedModelBuilder { int parseFlags= quickParseMode ? ITranslationUnit.AST_SKIP_ALL_HEADERS : ITranslationUnit.AST_SKIP_INDEXED_HEADERS; if (!(elementInfo instanceof ASTHolderTUInfo)) { parseFlags |= ITranslationUnit.AST_SKIP_FUNCTION_BODIES; - } - else { + } else { parseFlags |= ITranslationUnit.AST_CONFIGURE_USING_SOURCE_CONTEXT; } parseFlags |= ITranslationUnit.AST_SKIP_TRIVIAL_EXPRESSIONS_IN_AGGREGATE_INITIALIZERS; + parseFlags |= ITranslationUnit.AST_PARSE_INACTIVE_CODE; final IASTTranslationUnit ast; try { ast= fTranslationUnit.getAST(index, parseFlags, fProgressMonitor); @@ -193,14 +193,13 @@ public class CModelBuilder2 implements IContributedModelBuilder { */ private void buildModel(IASTTranslationUnit ast) throws CModelException, DOMException { fVisibilityStack= new Stack(); - fAllNamespaces= new HashSet(); + fEqualElements= new HashMap(); // includes final IASTPreprocessorIncludeStatement[] includeDirectives= ast.getIncludeDirectives(); - Set allIncludes= new HashSet(); for (IASTPreprocessorIncludeStatement includeDirective : includeDirectives) { if (isLocalToFile(includeDirective)) { - createInclusion(fTranslationUnit, includeDirective, allIncludes); + createInclusion(fTranslationUnit, includeDirective); } } // macros @@ -217,6 +216,7 @@ public class CModelBuilder2 implements IContributedModelBuilder { createDeclaration(fTranslationUnit, declaration); } } + fEqualElements.clear(); // sort by offset final List children= fTranslationUnit.getElementInfo().internalGetChildren(); @@ -264,18 +264,15 @@ public class CModelBuilder2 implements IContributedModelBuilder { return node.isPartOfTranslationUnitFile(); } - private Include createInclusion(Parent parent, IASTPreprocessorIncludeStatement inclusion, Set allIncludes) throws CModelException{ + private Include createInclusion(Parent parent, IASTPreprocessorIncludeStatement inclusion) throws CModelException{ // create element final IASTName name= inclusion.getName(); Include element= new Include(parent, ASTStringUtil.getSimpleName(name), inclusion.isSystemInclude()); element.setFullPathName(inclusion.getPath()); + setIndex(element); + element.setActive(inclusion.isActive()); element.setResolved(inclusion.isResolved()); - // if there is a duplicate include, also set the index - if (!allIncludes.add(element)) { - element.setIndex(allIncludes.size()); - allIncludes.add(element); - } // add to parent parent.addChild(element); // set positions @@ -284,10 +281,22 @@ public class CModelBuilder2 implements IContributedModelBuilder { return element; } + private void setIndex(SourceManipulation element) { + int[] idx= fEqualElements.get(element); + if (idx == null) { + idx= new int[] {0}; + fEqualElements.put(element, idx); + } else { + element.setIndex(++idx[0]); + } + } + private Macro createMacro(Parent parent, IASTPreprocessorMacroDefinition macro) throws CModelException{ // create element final IASTName name= macro.getName(); Macro element= new Macro(parent, ASTStringUtil.getSimpleName(name)); + setIndex(element); + element.setActive(macro.isActive()); // add to parent parent.addChild(element); // set positions @@ -479,11 +488,8 @@ public class CModelBuilder2 implements IContributedModelBuilder { final IASTName name= declaration.getName(); final String nsName= ASTStringUtil.getQualifiedName(name); final Namespace element= new Namespace(parent, nsName); - // if there is a duplicate namespace, also set the index - if (!fAllNamespaces.add(element)) { - element.setIndex(fAllNamespaces.size()); - fAllNamespaces.add(element); - } + setIndex(element); + // add to parent parent.addChild(element); // set positions @@ -499,15 +505,12 @@ public class CModelBuilder2 implements IContributedModelBuilder { element.setTypeName(type); - final Set savedNamespaces= fAllNamespaces; - fAllNamespaces= new HashSet(); IASTDeclaration[] nsDeclarations= declaration.getDeclarations(); for (IASTDeclaration nsDeclaration : nsDeclarations) { if (declaration.getFileLocation() != null || isLocalToFile(nsDeclaration)) { createDeclaration(element, nsDeclaration); } } - fAllNamespaces= savedNamespaces; } private StructureDeclaration createElaboratedTypeDeclaration(Parent parent, IASTElaboratedTypeSpecifier elaboratedTypeSpecifier, boolean isTemplate) throws CModelException{ @@ -547,6 +550,7 @@ public class CModelBuilder2 implements IContributedModelBuilder { } else { element= new StructureDeclaration(parent, className, kind); } + setIndex(element); element.setTypeName(type); // add to parent @@ -571,6 +575,8 @@ public class CModelBuilder2 implements IContributedModelBuilder { final IASTName astEnumName= enumSpecifier.getName(); final String enumName= ASTStringUtil.getSimpleName(astEnumName); final Enumeration element= new Enumeration (parent, enumName); + setIndex(element); + // add to parent parent.addChild(element); final IASTEnumerator[] enumerators= enumSpecifier.getEnumerators(); @@ -592,6 +598,8 @@ public class CModelBuilder2 implements IContributedModelBuilder { private Enumerator createEnumerator(Parent enumarator, IASTEnumerator enumDef) throws CModelException{ final IASTName astEnumName= enumDef.getName(); final Enumerator element= new Enumerator (enumarator, ASTStringUtil.getSimpleName(astEnumName)); + setIndex(element); + IASTExpression initialValue= enumDef.getValue(); if(initialValue != null){ element.setConstantExpression(ASTSignatureUtil.getExpressionString(initialValue)); @@ -643,6 +651,7 @@ public class CModelBuilder2 implements IContributedModelBuilder { StructureTemplate classTemplate= new StructureTemplate(parent, kind, className); element= classTemplate; } + setIndex(element); if (compositeTypeSpecifier instanceof ICPPASTCompositeTypeSpecifier) { // store super classes names @@ -712,6 +721,7 @@ public class CModelBuilder2 implements IContributedModelBuilder { String name= ASTStringUtil.getSimpleName(astTypedefName); final TypeDef element= new TypeDef(parent, name); + setIndex(element); String typeName= ASTStringUtil.getSignatureString(declSpecifier, declarator); element.setTypeName(typeName); @@ -752,6 +762,7 @@ public class CModelBuilder2 implements IContributedModelBuilder { || CModelBuilder2.getScope(astVariableName) instanceof ICPPClassScope) { // field Field newElement= new Field(parent, variableName); + setIndex(newElement); if (specifier instanceof ICPPASTDeclSpecifier) { final ICPPASTDeclSpecifier cppSpecifier= (ICPPASTDeclSpecifier)specifier; newElement.setMutable(cppSpecifier.getStorageClass() == ICPPASTDeclSpecifier.sc_mutable); @@ -777,6 +788,7 @@ public class CModelBuilder2 implements IContributedModelBuilder { element= newElement; } } + setIndex(element); element.setTypeName(ASTStringUtil.getSignatureString(specifier, declarator)); info= element.getSourceManipulationInfo(); } @@ -867,6 +879,8 @@ public class CModelBuilder2 implements IContributedModelBuilder { methodElement.setParameterTypes(parameterTypes); methodElement.setReturnType(returnType); methodElement.setConst(cppFunctionDeclarator.isConst()); + setIndex(element); + final MethodInfo methodInfo= methodElement.getMethodInfo(); info= methodInfo; ICPPMethod methodBinding= null; @@ -929,6 +943,8 @@ public class CModelBuilder2 implements IContributedModelBuilder { } element.setParameterTypes(parameterTypes); element.setReturnType(returnType); + setIndex(element); + info= element.getFunctionInfo(); info.setConst(cppFunctionDeclarator.isConst()); } @@ -938,6 +954,8 @@ public class CModelBuilder2 implements IContributedModelBuilder { element= new Function(parent, functionName); element.setParameterTypes(parameterTypes); element.setReturnType(returnType); + setIndex(element); + info= element.getFunctionInfo(); } @@ -988,6 +1006,7 @@ public class CModelBuilder2 implements IContributedModelBuilder { methodElement.setParameterTypes(parameterTypes); methodElement.setReturnType(returnType); methodElement.setConst(cppFunctionDeclarator.isConst()); + setIndex(element); final MethodInfo methodInfo= methodElement.getMethodInfo(); info= methodInfo; if (declSpecifier instanceof ICPPASTDeclSpecifier) { @@ -1009,6 +1028,8 @@ public class CModelBuilder2 implements IContributedModelBuilder { } element.setParameterTypes(parameterTypes); element.setReturnType(returnType); + setIndex(element); + info= (FunctionInfo)element.getElementInfo(); info.setConst(cppFunctionDeclarator.isConst()); } @@ -1020,6 +1041,8 @@ public class CModelBuilder2 implements IContributedModelBuilder { } element.setParameterTypes(parameterTypes); element.setReturnType(returnType); + setIndex(element); + info= (FunctionInfo)element.getElementInfo(); } else { assert false; @@ -1044,6 +1067,7 @@ public class CModelBuilder2 implements IContributedModelBuilder { // create the element IASTName name= usingDirDeclaration.getQualifiedName(); Using element= new Using(parent, ASTStringUtil.getQualifiedName(name), true); + setIndex(element); // add to parent parent.addChild(element); @@ -1058,6 +1082,7 @@ public class CModelBuilder2 implements IContributedModelBuilder { // create the element IASTName name= usingDeclaration.getName(); Using element= new Using(parent, ASTStringUtil.getSimpleName(name), false); + setIndex(element); // add to parent parent.addChild(element); diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Include.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Include.java index 2e0fb8b97f3..595814c1068 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Include.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Include.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 QNX Software Systems and others. + * Copyright (c) 2000, 2009 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,8 +8,8 @@ * Contributors: * QNX Software Systems - Initial API and implementation * Anton Leherbauer (Wind River Systems) + * Markus Schorn (Wind River Systems) *******************************************************************************/ - package org.eclipse.cdt.internal.core.model; import org.eclipse.cdt.core.model.ICElement; @@ -17,11 +17,9 @@ import org.eclipse.cdt.core.model.IInclude; public class Include extends SourceManipulation implements IInclude { - private final boolean standard; private String fullPath; - private boolean fIsActive= true; + private final boolean standard; private boolean fIsResolved= true; - private int fIndex= 0; public Include(ICElement parent, String name, boolean isStandard) { super(parent, name, ICElement.C_INCLUDE); @@ -58,17 +56,6 @@ public class Include extends SourceManipulation implements IInclude { this.fullPath = fullPath; } - public void setActive(boolean active) { - fIsActive= active; - } - - /* - * @see org.eclipse.cdt.core.model.IInclude#isActive() - */ - public boolean isActive() { - return fIsActive; - } - public void setResolved(boolean resolved) { fIsResolved= resolved; } @@ -80,25 +67,12 @@ public class Include extends SourceManipulation implements IInclude { return fIsResolved; } - /** - * Set the index of this include, in case the same include is referenced - * multiple times. - * - * @param index - */ - public void setIndex(int index) { - fIndex= index; - } - /* * @see org.eclipse.cdt.internal.core.model.CElement#equals(java.lang.Object) */ @Override public boolean equals(Object other) { if (other instanceof IInclude && equals(this, (IInclude) other)) { - if (other instanceof Include) { - return fIndex == ((Include)other).fIndex; - } return true; } return false; diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Namespace.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Namespace.java index d25d174b7e4..52524b8e2af 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Namespace.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Namespace.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2002, 2008 IBM Corporation and others. + * Copyright (c) 2002, 2009 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 @@ -8,6 +8,7 @@ * Contributors: * Rational Software - Initial API and implementation * Anton Leherbauer (Wind River Systems) + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.model; @@ -18,7 +19,6 @@ import org.eclipse.cdt.core.model.INamespace; public class Namespace extends SourceManipulation implements INamespace{ String typeName = ""; //$NON-NLS-1$ - int fIndex; public Namespace(ICElement parent, String name) { super(parent, name, ICElement.C_NAMESPACE); } @@ -39,28 +39,14 @@ public class Namespace extends SourceManipulation implements INamespace{ this.typeName = typeName; } - /** - * Set the index of this namespace, in case the same namespace is referenced - * multiple times. - * - * @param index - */ - public void setIndex(int index) { - fIndex= index; - } - /* * @see org.eclipse.cdt.internal.core.model.CElement#equals(java.lang.Object) */ @Override public boolean equals(Object other) { if (other instanceof INamespace && equals(this, (INamespace) other)) { - if (other instanceof Namespace) { - return fIndex == ((Namespace)other).fIndex; - } return true; } return false; } - } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/SourceManipulation.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/SourceManipulation.java index 23b93eb4f84..6e58b040341 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/SourceManipulation.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/SourceManipulation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 QNX Software Systems and others. + * Copyright (c) 2000, 2009 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * QNX Software Systems - Initial API and implementation * Anton Leherbauer (Wind River Systems) + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.model; @@ -41,6 +42,8 @@ public class SourceManipulation extends Parent implements ISourceManipulation, I * An empty list of Strings */ protected static final String[] fgEmptyStrings = {}; + private boolean fIsActive= true; + private short fIndex= 0; public SourceManipulation(ICElement parent, String name, int type) { super(parent, name, type); @@ -350,4 +353,33 @@ public class SourceManipulation extends Parent implements ISourceManipulation, I return CElement.CEM_SOURCEELEMENT; } + public boolean isActive() { + return fIsActive; + } + + public int getIndex() { + return fIndex; + } + + public void setActive(boolean active) { + fIsActive= active; + } + + public void setIndex(int i) { + fIndex= (short) i; + } + + @Override + public int hashCode() { + return Util.combineHashCodes(fIndex, super.hashCode()); + } + + @Override + public boolean equals(Object other) { + if (other instanceof ISourceReference) { + if (fIndex != ((ISourceReference) other).getIndex()) + return false; + } + return super.equals(other); + } } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/SourceManipulationInfo.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/SourceManipulationInfo.java index 9b7024337fe..3378c3ee372 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/SourceManipulationInfo.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/SourceManipulationInfo.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 QNX Software Systems and others. + * Copyright (c) 2000, 2009 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,6 +7,7 @@ * * Contributors: * QNX Software Systems - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.model; @@ -33,13 +34,9 @@ class SourceManipulationInfo extends CElementInfo { protected int fStartLine; protected int fEndLine; - - int modifiers; - protected SourceManipulationInfo(CElement element) { super(element); setIsStructureKnown(true); - modifiers = 0; } public void setPos(int startPos, int length) { @@ -209,7 +206,7 @@ class SourceManipulationInfo extends CElementInfo { * @return int */ public int getModifiers(){ - return modifiers; + return 0; } /** diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java index 777a9a535fb..c23b66fe54d 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnit.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 QNX Software Systems and others. + * Copyright (c) 2000, 2009 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -401,6 +401,10 @@ public class TranslationUnit extends Openable implements ITranslationUnit { return super.equals(o) && !((ITranslationUnit) o).isWorkingCopy(); } + public IWorkingCopy findSharedWorkingCopy() { + return findSharedWorkingCopy(null); + } + public IWorkingCopy findSharedWorkingCopy(IBufferFactory factory) { // if factory is null, default factory must be used @@ -456,6 +460,11 @@ public class TranslationUnit extends Openable implements ITranslationUnit { } } + public IWorkingCopy getSharedWorkingCopy(IProgressMonitor monitor, IProblemRequestor requestor) + throws CModelException { + return getSharedWorkingCopy(monitor, null, requestor); + } + public IWorkingCopy getSharedWorkingCopy(IProgressMonitor monitor,IBufferFactory factory) throws CModelException { return getSharedWorkingCopy(monitor, factory, null); @@ -493,7 +502,11 @@ public class TranslationUnit extends Openable implements ITranslationUnit { return this.getWorkingCopy(null, null); } - public IWorkingCopy getWorkingCopy(IProgressMonitor monitor, IBufferFactory factory)throws CModelException{ + public IWorkingCopy getWorkingCopy(IProgressMonitor monitor) throws CModelException { + return getWorkingCopy(monitor, null); + } + + public IWorkingCopy getWorkingCopy(IProgressMonitor monitor, IBufferFactory factory) throws CModelException{ WorkingCopy workingCopy; IFile file= getFile(); if (file != null) { @@ -638,7 +651,7 @@ public class TranslationUnit extends Openable implements ITranslationUnit { */ private void parse(Map newElements, IProgressMonitor monitor) { boolean quickParseMode = ! (CCorePlugin.getDefault().useStructuralParseMode()); - IContributedModelBuilder mb = LanguageManager.getInstance().getContributedModelBuilderFor(this); + IContributedModelBuilder mb = LanguageManager.getInstance().getContributedModelBuilderFor((ITranslationUnit) this); if (mb == null) { parseUsingCModelBuilder(newElements, quickParseMode, monitor); } else { @@ -823,6 +836,9 @@ public class TranslationUnit extends Openable implements ITranslationUnit { if ((style & AST_SKIP_TRIVIAL_EXPRESSIONS_IN_AGGREGATE_INITIALIZERS) != 0) { options |= ILanguage.OPTION_SKIP_TRIVIAL_EXPRESSIONS_IN_AGGREGATE_INITIALIZERS; } + if ((style & AST_PARSE_INACTIVE_CODE) != 0) { + options |= ILanguage.OPTION_PARSE_INACTIVE_CODE; + } if (isSourceUnit()) { options |= ILanguage.OPTION_IS_SOURCE_UNIT; } @@ -1130,4 +1146,11 @@ public class TranslationUnit extends Openable implements ITranslationUnit { return CElement.CEM_TRANSLATIONUNIT; } + public boolean isActive() { + return true; + } + + public int getIndex() { + return 0; + } } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ext/CElementHandle.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ext/CElementHandle.java index 9ae34d53c11..611c5249c0c 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ext/CElementHandle.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ext/CElementHandle.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2006, 2009 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 @@ -317,4 +317,11 @@ abstract class CElementHandle implements ICElementHandle, ISourceReference { } } + public boolean isActive() { + return true; + } + + public int getIndex() { + return 0; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorMacroDefinition.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorMacroDefinition.java index a742d7ca0aa..ba51cd823d7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorMacroDefinition.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorMacroDefinition.java @@ -29,18 +29,9 @@ public interface IASTPreprocessorMacroDefinition extends /** * Get the macro name. - * - * @return IASTName */ public IASTName getName(); - /** - * Set the macro name. - * - * @param name - */ - public void setName(IASTName name); - /** * Returns the macro expansion, or an empty string for dynamic style macros. */ @@ -53,11 +44,20 @@ public interface IASTPreprocessorMacroDefinition extends */ public IASTFileLocation getExpansionLocation(); + /** - * Set the macro expansion. - * - * @param exp - * String + * Returns whether this macro definition occurs in active code. + * @since 5.1 */ - public void setExpansion(String exp); + public boolean isActive(); + + /** + * @noreference This method is not intended to be referenced by clients. + */ + @Deprecated public void setName(IASTName name); + + /** + * @noreference This method is not intended to be referenced by clients. + */ + @Deprecated public void setExpansion(String exp); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/AbstractCLikeLanguage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/AbstractCLikeLanguage.java index 717f8626dad..2f081b772b9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/AbstractCLikeLanguage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/AbstractCLikeLanguage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 IBM Corporation and others. + * Copyright (c) 2007, 2009 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 @@ -114,6 +114,7 @@ public abstract class AbstractCLikeLanguage extends AbstractLanguage implements final IScanner scanner= createScanner(reader, scanInfo, codeReaderFactory, log); scanner.setComputeImageLocations((options & OPTION_NO_IMAGE_LOCATIONS) == 0); + scanner.setProcessInactiveCode((options & OPTION_PARSE_INACTIVE_CODE) != 0); final ISourceCodeParser parser= createParser(scanner, log, index, false, options); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScanner.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScanner.java index 237ab119b2d..e15c232bc9e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScanner.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScanner.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2008 IBM Corporation and others. + * Copyright (c) 2003, 2009 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 @@ -82,4 +82,20 @@ public interface IScanner { * @since 5.0 */ public void setComputeImageLocations(boolean val); + + /** + * Toggles generation of tokens for inactive code branches. When turned on, + * each inactive code branch is preceded by a token of kind {@link IToken#tINACTIVE_CODE_START} and + * succeeded by one of kind {@link IToken#tINACTIVE_CODE_END}. + * + * @noreference This method is not intended to be referenced by clients. + */ + public void setProcessInactiveCode(boolean val); + + /** + * When in inactive code, skips all tokens up to the end of the inactive code section. + *

Note, token after calling this method may be another token of type {@link IToken#tINACTIVE_CODE_START}. + * @noreference This method is not intended to be referenced by clients. + */ + public void skipInactiveCode() throws OffsetLimitReachedException; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IToken.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IToken.java index 1fad501f5d7..73f4a80081b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IToken.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IToken.java @@ -39,195 +39,155 @@ public interface IToken { int FIRST_RESERVED_SCANNER= -100; int LAST_RESERVED_SCANNER= -1; - static public final int tIDENTIFIER = 1; - static public final int tINTEGER = 2; - static public final int tCOLONCOLON = 3; - static public final int tCOLON = 4; - static public final int tSEMI = 5; - static public final int tCOMMA = 6; - static public final int tQUESTION = 7; - static public final int tLPAREN = 8; - static public final int tRPAREN = 9; - static public final int tLBRACKET = 10; - static public final int tRBRACKET = 11; - static public final int tLBRACE = 12; - static public final int tRBRACE = 13; - static public final int tPLUSASSIGN = 14; - static public final int tINCR = 15; - static public final int tPLUS = 16; - static public final int tMINUSASSIGN = 17; - static public final int tDECR = 18; - static public final int tARROWSTAR = 19; - static public final int tARROW = 20; - static public final int tMINUS = 21; - static public final int tSTARASSIGN = 22; - static public final int tSTAR = 23; - static public final int tMODASSIGN = 24; - static public final int tMOD = 25; - static public final int tXORASSIGN = 26; - static public final int tXOR = 27; - static public final int tAMPERASSIGN = 28; - static public final int tAND = 29; - static public final int tAMPER = 30; - static public final int tBITORASSIGN = 31; - static public final int tOR = 32; - static public final int tBITOR = 33; - static public final int tBITCOMPLEMENT = 34; - static public final int tNOTEQUAL = 35; - static public final int tNOT = 36; - static public final int tEQUAL = 37; - static public final int tASSIGN = 38; - static public final int tUNKNOWN_CHAR= 39; - static public final int tSHIFTL = 40; - static public final int tLTEQUAL = 41; - static public final int tLT = 42; - static public final int tSHIFTRASSIGN = 43; - static public final int tSHIFTR = 44; - static public final int tGTEQUAL = 45; - static public final int tGT = 46; - static public final int tSHIFTLASSIGN = 47; - static public final int tELLIPSIS = 48; - static public final int tDOTSTAR = 49; - static public final int tDOT = 50; - static public final int tDIVASSIGN = 51; - static public final int tDIV = 52; + int tIDENTIFIER = 1; + int tINTEGER = 2; + int tCOLONCOLON = 3; + int tCOLON = 4; + int tSEMI = 5; + int tCOMMA = 6; + int tQUESTION = 7; + int tLPAREN = 8; + int tRPAREN = 9; + int tLBRACKET = 10; + int tRBRACKET = 11; + int tLBRACE = 12; + int tRBRACE = 13; + int tPLUSASSIGN = 14; + int tINCR = 15; + int tPLUS = 16; + int tMINUSASSIGN = 17; + int tDECR = 18; + int tARROWSTAR = 19; + int tARROW = 20; + int tMINUS = 21; + int tSTARASSIGN = 22; + int tSTAR = 23; + int tMODASSIGN = 24; + int tMOD = 25; + int tXORASSIGN = 26; + int tXOR = 27; + int tAMPERASSIGN = 28; + int tAND = 29; + int tAMPER = 30; + int tBITORASSIGN = 31; + int tOR = 32; + int tBITOR = 33; + int tBITCOMPLEMENT = 34; + int tNOTEQUAL = 35; + int tNOT = 36; + int tEQUAL = 37; + int tASSIGN = 38; + int tUNKNOWN_CHAR= 39; + int tSHIFTL = 40; + int tLTEQUAL = 41; + int tLT = 42; + int tSHIFTRASSIGN = 43; + int tSHIFTR = 44; + int tGTEQUAL = 45; + int tGT = 46; + int tSHIFTLASSIGN = 47; + int tELLIPSIS = 48; + int tDOTSTAR = 49; + int tDOT = 50; + int tDIVASSIGN = 51; + int tDIV = 52; - /** @deprecated use {@link #tAND} */ - @Deprecated - static public final int t_and = 54; - /** @deprecated use {@link #tAMPERASSIGN} */ - @Deprecated - static public final int t_and_eq = 55; - - static public final int t_asm = 56; - static public final int t_auto = 57; - - /** @deprecated use {@link #tAMPER} */ - @Deprecated - static public final int t_bitand = 58; - /** @deprecated use {@link #tBITOR} */ - @Deprecated - static public final int t_bitor = 59; - - static public final int t_bool = 60; - static public final int t_break = 61; - static public final int t_case = 62; - static public final int t_catch = 63; - static public final int t_char = 64; - static public final int t_class = 65; + /** @deprecated use {@link #tAND} */ @Deprecated int t_and = 54; + /** @deprecated use {@link #tAMPERASSIGN} */ @Deprecated int t_and_eq = 55; + int t_asm = 56; + int t_auto = 57; + /** @deprecated use {@link #tAMPER} */ @Deprecated int t_bitand = 58; + /** @deprecated use {@link #tBITOR} */ @Deprecated int t_bitor = 59; + int t_bool = 60; + int t_break = 61; + int t_case = 62; + int t_catch = 63; + int t_char = 64; + int t_class = 65; + /** @deprecated use {@link #tBITCOMPLEMENT} */ @Deprecated int tCOMPL= tBITCOMPLEMENT; + /** @deprecated use {@link #tBITCOMPLEMENT} */ @Deprecated int t_compl = 66; + int t_const = 67; - /** @deprecated use {@link #tBITCOMPLEMENT} */ - @Deprecated - static public final int tCOMPL= tBITCOMPLEMENT; - /** @deprecated use {@link #tBITCOMPLEMENT} */ - @Deprecated - static public final int t_compl = 66; - - static public final int t_const = 67; - static public final int t_const_cast = 69; - static public final int t_continue = 70; - static public final int t_default = 71; - static public final int t_delete = 72; - static public final int t_do = 73; - static public final int t_double = 74; - static public final int t_dynamic_cast = 75; - static public final int t_else = 76; - static public final int t_enum = 77; - static public final int t_explicit = 78; - static public final int t_export = 79; - static public final int t_extern = 80; - static public final int t_false = 81; - static public final int t_float = 82; - static public final int t_for = 83; - static public final int t_friend = 84; - static public final int t_goto = 85; - static public final int t_if = 86; - static public final int t_inline = 87; - static public final int t_int = 88; - static public final int t_long = 89; - static public final int t_mutable = 90; - static public final int t_namespace = 91; - static public final int t_new = 92; - - /** @deprecated use {@link #tNOT} */ - @Deprecated - static public final int t_not = 93; - /** @deprecated use {@link #tNOTEQUAL} */ - @Deprecated - static public final int t_not_eq = 94; - - static public final int t_operator = 95; - - /** @deprecated use {@link #tOR} */ - @Deprecated - static public final int t_or = 96; - /** @deprecated use {@link #tBITORASSIGN} */ - @Deprecated - static public final int t_or_eq = 97; - - static public final int t_private = 98; - static public final int t_protected = 99; - static public final int t_public = 100; - static public final int t_register = 101; - static public final int t_reinterpret_cast = 102; - static public final int t_return = 103; - static public final int t_short = 104; - static public final int t_sizeof = 105; - static public final int t_static = 106; - static public final int t_static_cast = 107; - static public final int t_signed = 108; - static public final int t_struct = 109; - static public final int t_switch = 110; - static public final int t_template = 111; - static public final int t_this = 112; - static public final int t_throw = 113; - static public final int t_true = 114; - static public final int t_try = 115; - static public final int t_typedef = 116; - static public final int t_typeid = 117; - static public final int t_typename = 118; - static public final int t_union = 119; - static public final int t_unsigned = 120; - static public final int t_using = 121; - static public final int t_virtual = 122; - static public final int t_void = 123; - static public final int t_volatile = 124; - static public final int t_wchar_t = 125; - static public final int t_while = 126; - - /** @deprecated use {@link #tXOR} */ - @Deprecated - static public final int t_xor = 127; - /** @deprecated use {@link #tXORASSIGN} */ - @Deprecated - static public final int t_xor_eq = 128; - - static public final int tFLOATINGPT = 129; - static public final int tSTRING = 130; - static public final int tLSTRING = 131; - static public final int tCHAR = 132; - static public final int tLCHAR = 133; - static public final int t__Bool = 134; - static public final int t__Complex = 135; - static public final int t__Imaginary = 136; - static public final int t_restrict = 137; - - /** @deprecated don't use it */ - @Deprecated - static public final int tMACROEXP = 138; - - static public final int tPOUND= 138; - static public final int tPOUNDPOUND = 139; - static public final int tCOMPLETION = 140; - static public final int tEOC = 141; // End of Completion - - /** @deprecated don't use it */ - @Deprecated - static public final int tCOMMENT = 142; - /** @deprecated don't use it */ - @Deprecated - static public final int tBLOCKCOMMENT = 143; - static public final int tEND_OF_INPUT= 144; + int t_const_cast = 69; + int t_continue = 70; + int t_default = 71; + int t_delete = 72; + int t_do = 73; + int t_double = 74; + int t_dynamic_cast = 75; + int t_else = 76; + int t_enum = 77; + int t_explicit = 78; + int t_export = 79; + int t_extern = 80; + int t_false = 81; + int t_float = 82; + int t_for = 83; + int t_friend = 84; + int t_goto = 85; + int t_if = 86; + int t_inline = 87; + int t_int = 88; + int t_long = 89; + int t_mutable = 90; + int t_namespace = 91; + int t_new = 92; + /** @deprecated use {@link #tNOT} */ @Deprecated int t_not = 93; + /** @deprecated use {@link #tNOTEQUAL} */ @Deprecated int t_not_eq = 94; + int t_operator = 95; + /** @deprecated use {@link #tOR} */ @Deprecated int t_or = 96; + /** @deprecated use {@link #tBITORASSIGN} */ @Deprecated int t_or_eq = 97; + int t_private = 98; + int t_protected = 99; + int t_public = 100; + int t_register = 101; + int t_reinterpret_cast = 102; + int t_return = 103; + int t_short = 104; + int t_sizeof = 105; + int t_static = 106; + int t_static_cast = 107; + int t_signed = 108; + int t_struct = 109; + int t_switch = 110; + int t_template = 111; + int t_this = 112; + int t_throw = 113; + int t_true = 114; + int t_try = 115; + int t_typedef = 116; + int t_typeid = 117; + int t_typename = 118; + int t_union = 119; + int t_unsigned = 120; + int t_using = 121; + int t_virtual = 122; + int t_void = 123; + int t_volatile = 124; + int t_wchar_t = 125; + int t_while = 126; + /** @deprecated use {@link #tXOR} */ @Deprecated int t_xor = 127; + /** @deprecated use {@link #tXORASSIGN} */ @Deprecated int t_xor_eq = 128; + int tFLOATINGPT = 129; + int tSTRING = 130; + int tLSTRING = 131; + int tCHAR = 132; + int tLCHAR = 133; + int t__Bool = 134; + int t__Complex = 135; + int t__Imaginary = 136; + int t_restrict = 137; + /** @deprecated don't use it */ @Deprecated int tMACROEXP = 138; + int tPOUND= 138; + int tPOUNDPOUND = 139; + int tCOMPLETION = 140; + int tEOC = 141; // End of Completion + /** @deprecated don't use it */ @Deprecated int tCOMMENT = 142; + /** @deprecated don't use it */ @Deprecated int tBLOCKCOMMENT = 143; + int tEND_OF_INPUT= 144; + /** @since 5.1 */ int tINACTIVE_CODE_START= 145; + /** @since 5.1 */ int tINACTIVE_CODE_SEPARATOR= 146; + /** @since 5.1 */ int tINACTIVE_CODE_END = 147; int FIRST_RESERVED_IGCCToken = 150; int LAST_RESERVED_IGCCToken = 199; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java index 663b219f51f..08f5f810a1d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2008 IBM Corporation and others. + * Copyright (c) 2005, 2009 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 @@ -206,29 +206,35 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { } /** - * Look Ahead in the token list to see what is coming. - * - * @param i - * How far ahead do you wish to peek? + * Returns the next token without advancing + */ + protected IToken mark() throws EndOfFileException { + return currToken == null ? currToken = fetchToken(true) : currToken; + } + + /** + * Roll back to a previous point, reseting the queue of tokens. + * @param mark a token previously obtained via {@link #mark()}. + */ + protected void backup(IToken mark) { + currToken = mark; + } + + /** + * Look ahead in the token list to see what is coming. + * @param i number of tokens to look ahead, must be greater or equal to 0. * @return the token you wish to observe - * @throws EndOfFileException - * if looking ahead encounters EOF, throw EndOfFile */ protected IToken LA(int i) throws EndOfFileException { - + assert i >= 0; if (isCancelled) { throw new ParseError(ParseError.ParseErrorKind.TIMEOUT_OR_CANCELLED); } - - if (i < 1) // can't go backwards - return null; - if (currToken == null) - currToken = fetchToken(); - IToken retToken = currToken; + IToken retToken= mark(); for (; i > 1; --i) { retToken = retToken.getNext(); if (retToken == null) - retToken = fetchToken(); + retToken = fetchToken(true); } return retToken; } @@ -246,12 +252,8 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { /** * Look ahead in the token list and return the token type. - * - * @param i - * How far ahead do you wish to peek? + * @param i number of tokens to look ahead, must be greater or equal to 0. * @return The type of that token - * @throws EndOfFileException - * if looking ahead encounters EOF, throw EndOfFile */ protected int LT(int i) throws EndOfFileException { return LA(i).getType(); @@ -295,37 +297,29 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { } /** - * Consume the next token available, regardless of the type. + * Consume the next token available, regardless of the type and returns it. * * @return The token that was consumed and removed from our buffer. * @throws EndOfFileException * If there is no token to consume. */ protected IToken consume() throws EndOfFileException { - if (currToken == null) { - currToken = fetchToken(); - } - - final IToken lastToken = currToken; - currToken= lastToken.getNext(); - return lastToken; + final IToken result= mark(); + currToken= result.getNext(); + return result; } /** - * Consume the next token available only if the type is as specified. + * If the type of the next token matches, it is consumed and returned. Otherwise a + * {@link BacktrackException} will be thrown. * - * @param type - * The type of token that you are expecting. - * @return the token that was consumed and removed from our buffer. - * @throws BacktrackException - * If LT(1) != type + * @param type the expected type of the next token. */ protected IToken consume(int type) throws EndOfFileException, BacktrackException { - final IToken la1= LA(1); - if (la1.getType() != type) - throwBacktrack(la1); - - return consume(); + final IToken result= consume(); + if (result.getType() != type) + throwBacktrack(result); + return result; } /** @@ -350,15 +344,15 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { } /** - * Fetches a token from the scanner. - * - * @return the next token from the scanner - * @throws EndOfFileException - * thrown when the scanner.nextToken() yields no tokens + * Fetches the next token from the scanner. */ - protected IToken fetchToken() throws EndOfFileException { + private IToken fetchToken(boolean skipInactive) throws EndOfFileException { try { - final IToken result= scanner.nextToken(); + IToken result= scanner.nextToken(); + while (result.getType() == IToken.tINACTIVE_CODE_START) { + scanner.skipInactiveCode(); + result= scanner.nextToken(); + } eofOffset= result.getEndOffset(); return result; } catch (OffsetLimitReachedException olre) { @@ -375,28 +369,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { throw exception; } - /** - * Mark our place in the buffer so that we could return to it should we have - * to. - * - * @return The current token. - * @throws EndOfFileException - * If there are no more tokens. - */ - protected IToken mark() throws EndOfFileException { - return currToken == null ? currToken = fetchToken() : currToken; - } - - /** - * Rollback to a previous point, reseting the queue of tokens. - * - * @param mark - * The point that we wish to restore to. - */ - protected void backup(IToken mark) { - currToken = mark; - } - /** * This is the single entry point for setting parsePassed to false */ 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 a0ebe901133..99b1a6deef4 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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 @@ -276,15 +276,17 @@ class ASTMacroDefinition extends ASTPreprocessorNode implements IASTPreprocessor private final ASTPreprocessorName fName; private final int fExpansionNumber; private final int fExpansionOffset; + private final boolean fActive; /** * Regular constructor. */ public ASTMacroDefinition(IASTTranslationUnit parent, IMacroBinding macro, - int startNumber, int nameNumber, int nameEndNumber, int expansionNumber, int endNumber) { + int startNumber, int nameNumber, int nameEndNumber, int expansionNumber, int endNumber, boolean active) { super(parent, IASTTranslationUnit.PREPROCESSOR_STATEMENT, startNumber, endNumber); fExpansionNumber= expansionNumber; fExpansionOffset= -1; + fActive= active; fName= new ASTPreprocessorDefinition(this, IASTPreprocessorMacroDefinition.MACRO_NAME, nameNumber, nameEndNumber, macro.getNameCharArray(), macro); } @@ -297,6 +299,7 @@ class ASTMacroDefinition extends ASTPreprocessorNode implements IASTPreprocessor fName= new ASTBuiltinName(this, IASTPreprocessorMacroDefinition.MACRO_NAME, floc, macro.getNameCharArray(), macro); fExpansionNumber= -1; fExpansionOffset= expansionOffset; + fActive= true; } @@ -357,6 +360,10 @@ class ASTMacroDefinition extends ASTPreprocessorNode implements IASTPreprocessor public String toString() { return getName().toString() + '=' + getExpansion(); } + + final public boolean isActive() { + return fActive; + } } class ASTMacroParameter extends ASTPreprocessorNode implements IASTFunctionStyleMacroParameter { @@ -379,8 +386,8 @@ class ASTFunctionStyleMacroDefinition extends ASTMacroDefinition implements IAST * Regular constructor. */ public ASTFunctionStyleMacroDefinition(IASTTranslationUnit parent, IMacroBinding macro, - int startNumber, int nameNumber, int nameEndNumber, int expansionNumber, int endNumber) { - super(parent, macro, startNumber, nameNumber, nameEndNumber, expansionNumber, endNumber); + int startNumber, int nameNumber, int nameEndNumber, int expansionNumber, int endNumber, boolean active) { + super(parent, macro, startNumber, nameNumber, nameEndNumber, expansionNumber, endNumber, active); } /** 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 e5edc98f486..914604dcfdd 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 @@ -49,6 +49,9 @@ import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator.EvalExce import org.eclipse.cdt.internal.core.parser.scanner.IncludeFileContent.InclusionKind; import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions; import org.eclipse.cdt.internal.core.parser.scanner.MacroDefinitionParser.InvalidMacroDefinitionException; +import org.eclipse.cdt.internal.core.parser.scanner.ScannerContext.BranchKind; +import org.eclipse.cdt.internal.core.parser.scanner.ScannerContext.CodeState; +import org.eclipse.cdt.internal.core.parser.scanner.ScannerContext.Conditional; import org.eclipse.core.runtime.IAdaptable; /** @@ -68,7 +71,6 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { private static final int ORIGIN_PREPROCESSOR_DIRECTIVE = OffsetLimitReachedException.ORIGIN_PREPROCESSOR_DIRECTIVE; private static final int ORIGIN_INACTIVE_CODE = OffsetLimitReachedException.ORIGIN_INACTIVE_CODE; -// private static final int ORIGIN_MACRO_EXPANSION = OffsetLimitReachedException.ORIGIN_MACRO_EXPANSION; private static final char[] EMPTY_CHAR_ARRAY = new char[0]; private static final char[] ONE = "1".toCharArray(); //$NON-NLS-1$ @@ -169,7 +171,6 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { final private String[] fIncludePaths; final private String[] fQuoteIncludePaths; private String[][] fPreIncludedFiles= null; -// private boolean fProcessInactiveCode= false; private int fContentAssistLimit= -1; private boolean fHandledCompletion= false; @@ -279,10 +280,9 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { fRootLexer.setContentAssistMode(offset); } - // mstodo -// public void setProcessInactiveCode(boolean val) { -// fProcessInactiveCode= val; -// } + public void setProcessInactiveCode(boolean val) { + fRootContext.setParseInactiveCode(val); + } public void setScanComments(boolean val) { } @@ -599,7 +599,19 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { return t1; } - private void appendStringContent(StringBuffer buf, Token t1) { + + public void skipInactiveCode() throws OffsetLimitReachedException { + final Lexer lexer= fCurrentContext.getLexer(); + if (lexer != null) { + CodeState state= fCurrentContext.getCodeState(); + while (state != CodeState.eActive) { + state= skipBranch(lexer, false); + } + fCurrentContext.clearInactiveCodeMarkerToken(); + } + } + + private void appendStringContent(StringBuffer buf, Token t1) { final char[] image= t1.getCharImage(); final int length= image.length; if (length > 1) { @@ -940,8 +952,6 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { /** * Assumes that the pound token has not yet been consumed - * @param ppdCtx - * @param startOffset offset in current file * @since 5.0 */ private void executeDirective(final Lexer lexer, final int startOffset, boolean withinExpansion) throws OffsetLimitReachedException { @@ -971,77 +981,53 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } // we have an identifier - boolean isProblem= false; final char[] name = ident.getCharImage(); final int type = fPPKeywords.get(name); int condEndOffset; switch (type) { case IPreprocessorDirective.ppImport: case IPreprocessorDirective.ppInclude: - if (withinExpansion) { - isProblem= true; - } else { - executeInclude(lexer, startOffset, false, true); - } + executeInclude(lexer, startOffset, false, fCurrentContext.getCodeState() == CodeState.eActive, withinExpansion); break; case IPreprocessorDirective.ppInclude_next: - if (withinExpansion) { - isProblem= true; - } else { - executeInclude(lexer, startOffset, true, true); - } + executeInclude(lexer, startOffset, true, fCurrentContext.getCodeState() == CodeState.eActive, withinExpansion); break; case IPreprocessorDirective.ppDefine: - executeDefine(lexer, startOffset); + executeDefine(lexer, startOffset, fCurrentContext.getCodeState() == CodeState.eActive); break; case IPreprocessorDirective.ppUndef: executeUndefine(lexer, startOffset); break; case IPreprocessorDirective.ppIfdef: - executeIfdef(lexer, startOffset, true, withinExpansion); + if (executeIfdef(lexer, startOffset, false, withinExpansion) == CodeState.eSkipInactive) + skipOverConditionalCode(lexer, withinExpansion); break; case IPreprocessorDirective.ppIfndef: - executeIfdef(lexer, startOffset, false, withinExpansion); + if (executeIfdef(lexer, startOffset, true, withinExpansion) == CodeState.eSkipInactive) + skipOverConditionalCode(lexer, withinExpansion); break; case IPreprocessorDirective.ppIf: - executeIf(lexer, startOffset, withinExpansion); - break; - case IPreprocessorDirective.ppElse: - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - if (fCurrentContext.changeBranch(ScannerContext.BRANCH_ELSE)) { - fLocationMap.encounterPoundElse(startOffset, ident.getEndOffset(), false); - skipOverConditionalCode(lexer, false, withinExpansion); - } - else { - handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, startOffset, ident.getEndOffset()); - } + if (executeIf(lexer, startOffset, false, withinExpansion) == CodeState.eSkipInactive) + skipOverConditionalCode(lexer, withinExpansion); break; case IPreprocessorDirective.ppElif: - int condOffset= lexer.nextToken().getOffset(); - condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - int endOffset= lexer.currentToken().getEndOffset(); - if (fCurrentContext.changeBranch(ScannerContext.BRANCH_ELIF)) { - fLocationMap.encounterPoundElif(startOffset, condOffset, condEndOffset, endOffset, false, IASTName.EMPTY_NAME_ARRAY); - skipOverConditionalCode(lexer, false, withinExpansion); - } - else { - handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, startOffset, condEndOffset); + if (executeIf(lexer, startOffset, true, withinExpansion) == CodeState.eSkipInactive) { + skipOverConditionalCode(lexer, withinExpansion); + } + break; + case IPreprocessorDirective.ppElse: + if (executeElse(lexer, startOffset, withinExpansion) == CodeState.eSkipInactive) { + skipOverConditionalCode(lexer, withinExpansion); } break; case IPreprocessorDirective.ppEndif: - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - if (fCurrentContext.changeBranch(ScannerContext.BRANCH_END)) { - fLocationMap.encounterPoundEndIf(startOffset, ident.getEndOffset()); - } - else { - handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, startOffset, ident.getEndOffset()); - } + executeEndif(lexer, startOffset, withinExpansion); break; case IPreprocessorDirective.ppWarning: case IPreprocessorDirective.ppError: - condOffset= lexer.nextToken().getOffset(); + int condOffset= lexer.nextToken().getOffset(); condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - endOffset= lexer.currentToken().getEndOffset(); + int endOffset= lexer.currentToken().getEndOffset(); final char[] warning= lexer.getInputChars(condOffset, condEndOffset); final int id= type == IPreprocessorDirective.ppError ? IProblem.PREPROCESSOR_POUND_ERROR @@ -1059,17 +1045,20 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); break; default: - isProblem= true; - break; - } - - if (isProblem) { - int endOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + endOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, ident.getCharImage(), startOffset, endOffset); + break; } } - private void executeInclude(final Lexer lexer, int poundOffset, boolean include_next, boolean active) throws OffsetLimitReachedException { + private void executeInclude(final Lexer lexer, int poundOffset, boolean include_next, boolean active, boolean withinExpansion) throws OffsetLimitReachedException { + if (withinExpansion) { + final char[] name= lexer.currentToken().getCharImage(); + final int endOffset = lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, name, poundOffset, endOffset); + return; + } + lexer.setInsideIncludeDirective(true); final Token header= lexer.nextToken(); lexer.setInsideIncludeDirective(false); @@ -1228,14 +1217,15 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } - private void executeDefine(final Lexer lexer, int startOffset) throws OffsetLimitReachedException { + private void executeDefine(final Lexer lexer, int startOffset, boolean isActive) throws OffsetLimitReachedException { try { ObjectStyleMacro macrodef = fMacroDefinitionParser.parseMacroDefinition(lexer, this); - fMacroDictionary.put(macrodef.getNameCharArray(), macrodef); + if (isActive) + fMacroDictionary.put(macrodef.getNameCharArray(), macrodef); + final Token name= fMacroDefinitionParser.getNameToken(); - fLocationMap.encounterPoundDefine(startOffset, name.getOffset(), name.getEndOffset(), - macrodef.getExpansionOffset(), macrodef.getExpansionEndOffset(), macrodef); + macrodef.getExpansionOffset(), macrodef.getExpansionEndOffset(), isActive, macrodef); } catch (InvalidMacroDefinitionException e) { lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); handleProblem(IProblem.PREPROCESSOR_INVALID_MACRO_DEFN, e.fName, e.fStartOffset, e.fEndOffset); @@ -1260,63 +1250,108 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { fLocationMap.encounterPoundUndef(definition, startOffset, name.getOffset(), name.getEndOffset(), endOffset, namechars); } - private void executeIfdef(Lexer lexer, int startOffset, boolean positive, boolean withinExpansion) throws OffsetLimitReachedException { + private CodeState executeIfdef(Lexer lexer, int offset, boolean isIfndef, boolean withinExpansion) throws OffsetLimitReachedException { final Token name= lexer.nextToken(); - final int tt= name.getType(); - if (tt != IToken.tIDENTIFIER) { - if (tt == IToken.tCOMPLETION) { - throw new OffsetLimitReachedException(ORIGIN_PREPROCESSOR_DIRECTIVE, name); - } - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - handleProblem(IProblem.PREPROCESSOR_DEFINITION_NOT_FOUND, name.getCharImage(), startOffset, name.getEndOffset()); - return; - } lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + final int tt= name.getType(); + final int nameOffset = name.getOffset(); + final int nameEndOffset = name.getEndOffset(); final int endOffset= lexer.currentToken().getEndOffset(); - final char[] namechars= name.getCharImage(); - PreprocessorMacro macro= fMacroDictionary.get(namechars); - boolean isActive= (macro != null) == positive; - - fCurrentContext.changeBranch(ScannerContext.BRANCH_IF); - if (positive) { - fLocationMap.encounterPoundIfdef(startOffset, name.getOffset(), name.getEndOffset(), endOffset, isActive, macro); - } - else { - fLocationMap.encounterPoundIfndef(startOffset, name.getOffset(), name.getEndOffset(), endOffset, isActive, macro); - } - - if ((macro == null) == positive) { - skipOverConditionalCode(lexer, true, withinExpansion); - } + + boolean isActive= false; + PreprocessorMacro macro= null; + final Conditional conditional= fCurrentContext.newBranch(BranchKind.eIf, withinExpansion); + if (conditional.canHaveActiveBranch(withinExpansion)) { + // we need an identifier + if (tt != IToken.tIDENTIFIER) { + if (tt == IToken.tCOMPLETION) { + throw new OffsetLimitReachedException(ORIGIN_PREPROCESSOR_DIRECTIVE, name); + } + // report problem and treat as inactive + handleProblem(IProblem.PREPROCESSOR_DEFINITION_NOT_FOUND, name.getCharImage(), offset, nameEndOffset); + } else { + final char[] namechars= name.getCharImage(); + macro= fMacroDictionary.get(namechars); + isActive= (macro == null) == isIfndef; + } + } + + if (isIfndef) { + fLocationMap.encounterPoundIfndef(offset, nameOffset, nameEndOffset, endOffset, isActive, macro); + } else { + fLocationMap.encounterPoundIfdef(offset, nameOffset, nameEndOffset, endOffset, isActive, macro); + } + return fCurrentContext.setBranchState(conditional, isActive, withinExpansion); } - private void executeIf(Lexer lexer, int startOffset, boolean withinExpansion) throws OffsetLimitReachedException { - boolean isActive= false; - TokenList condition= new TokenList(); - final int condOffset= lexer.nextToken().getOffset(); - final int condEndOffset= getTokensWithinPPDirective(true, condition, withinExpansion); - final int endOffset= lexer.currentToken().getEndOffset(); - - fExpressionEvaluator.clearMacrosInDefinedExpression(); - if (condition.first() == null) { - handleProblem(IProblem.SCANNER_EXPRESSION_SYNTAX_ERROR, null, startOffset, endOffset); - } - else { - try { - isActive= fExpressionEvaluator.evaluate(condition, fMacroDictionary, fLocationMap); - } catch (EvalException e) { - handleProblem(e.getProblemID(), e.getProblemArg(), condOffset, endOffset); - } - } - - fCurrentContext.changeBranch(ScannerContext.BRANCH_IF); - fLocationMap.encounterPoundIf(startOffset, condOffset, condEndOffset, endOffset, isActive, fExpressionEvaluator.clearMacrosInDefinedExpression()); + private CodeState executeIf(Lexer lexer, int startOffset, boolean isElif, boolean withinExpansion) throws OffsetLimitReachedException { + Conditional cond= fCurrentContext.newBranch(isElif ? BranchKind.eElif : BranchKind.eIf, withinExpansion); + if (cond == null) { + char[] name= lexer.currentToken().getCharImage(); + int condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, startOffset, condEndOffset); + return fCurrentContext.getCodeState(); + } - if (!isActive) { - skipOverConditionalCode(lexer, true, withinExpansion); - } + boolean isActive= false; + IASTName[] refs= IASTName.EMPTY_NAME_ARRAY; + int condOffset= lexer.nextToken().getOffset(); + int condEndOffset, endOffset; + + if (cond.canHaveActiveBranch(withinExpansion)) { + TokenList condition= new TokenList(); + condEndOffset= getTokensWithinPPDirective(true, condition, withinExpansion); + endOffset= lexer.currentToken().getEndOffset(); + + if (condition.first() == null) { + handleProblem(IProblem.SCANNER_EXPRESSION_SYNTAX_ERROR, null, startOffset, endOffset); + } else { + try { + fExpressionEvaluator.clearMacrosInDefinedExpression(); + isActive= fExpressionEvaluator.evaluate(condition, fMacroDictionary, fLocationMap); + refs = fExpressionEvaluator.clearMacrosInDefinedExpression(); + } catch (EvalException e) { + handleProblem(e.getProblemID(), e.getProblemArg(), condOffset, endOffset); + } + } + } else { + condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + endOffset= lexer.currentToken().getEndOffset(); + } + + if (isElif) { + fLocationMap.encounterPoundElif(startOffset, condOffset, condEndOffset, endOffset, isActive, refs); + } else { + fLocationMap.encounterPoundIf(startOffset, condOffset, condEndOffset, endOffset, isActive, refs); + } + return fCurrentContext.setBranchState(cond, isActive, withinExpansion); } + private CodeState executeElse(final Lexer lexer, final int startOffset,boolean withinExpansion) + throws OffsetLimitReachedException { + final int endOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + Conditional cond= fCurrentContext.newBranch(BranchKind.eElse, withinExpansion); + if (cond == null) { + handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, Keywords.cELSE, startOffset, endOffset); + return fCurrentContext.getCodeState(); + } + + final boolean isActive= cond.canHaveActiveBranch(withinExpansion); + fLocationMap.encounterPoundElse(startOffset, endOffset, isActive); + return fCurrentContext.setBranchState(cond, isActive, withinExpansion); + } + + private CodeState executeEndif(Lexer lexer, int startOffset, boolean withinExpansion) throws OffsetLimitReachedException { + final int endOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + final Conditional cond= fCurrentContext.newBranch(BranchKind.eEnd, withinExpansion); + if (cond == null) { + handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, Keywords.cENDIF, startOffset, endOffset); + } else { + fLocationMap.encounterPoundEndIf(startOffset, endOffset); + } + return fCurrentContext.getCodeState(); + } + /** * Runs the preprocessor on the rest of the line, storing the tokens in the holder supplied. * Macro expansion is reported to the location map. @@ -1326,6 +1361,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { */ private int getTokensWithinPPDirective(boolean isCondition, TokenList result, boolean withinExpansion) throws OffsetLimitReachedException { final ScannerContext scannerCtx= fCurrentContext; + scannerCtx.clearInactiveCodeMarkerToken(); int options= STOP_AT_NL; if (isCondition) options |= PROTECT_DEFINED; @@ -1357,135 +1393,69 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { return scannerCtx.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); } - private void skipOverConditionalCode(final Lexer lexer, boolean takeElseBranch, boolean withinExpansion) throws OffsetLimitReachedException { - int nesting= 0; - while(true) { - final Token pound= lexer.nextDirective(); - int tt= pound.getType(); - if (tt != IToken.tPOUND) { - if (tt == IToken.tCOMPLETION) { - throw new OffsetLimitReachedException(ORIGIN_INACTIVE_CODE, pound); // completion in inactive code - } - return; - } - final Token ident= lexer.nextToken(); - tt= ident.getType(); - if (tt != IToken.tIDENTIFIER) { - if (tt == IToken.tCOMPLETION) { - throw new OffsetLimitReachedException(ORIGIN_INACTIVE_CODE, ident); // completion in inactive directive - } - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - continue; - } - - // we have an identifier - final char[] name = ident.getCharImage(); - final int type = fPPKeywords.get(name); - switch (type) { - case IPreprocessorDirective.ppImport: - case IPreprocessorDirective.ppInclude: - if (withinExpansion) { - int endOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, ident.getCharImage(), pound.getOffset(), endOffset); - } else { - executeInclude(lexer, ident.getOffset(), false, false); - } - break; - case IPreprocessorDirective.ppInclude_next: - if (withinExpansion) { - int endOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, ident.getCharImage(), pound.getOffset(), endOffset); - } else { - executeInclude(lexer, ident.getOffset(), true, false); - } - break; - case IPreprocessorDirective.ppIfdef: - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - int endOffset= lexer.currentToken().getEndOffset(); - nesting++; - fCurrentContext.changeBranch(ScannerContext.BRANCH_IF); - fLocationMap.encounterPoundIfdef(pound.getOffset(), ident.getOffset(), ident.getEndOffset(), endOffset, false, null); - break; - case IPreprocessorDirective.ppIfndef: - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - endOffset= lexer.currentToken().getEndOffset(); - nesting++; - fCurrentContext.changeBranch(ScannerContext.BRANCH_IF); - fLocationMap.encounterPoundIfndef(pound.getOffset(), ident.getOffset(), ident.getEndOffset(), endOffset, false, null); - break; - case IPreprocessorDirective.ppIf: - int condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - endOffset= lexer.currentToken().getEndOffset(); - nesting++; - fCurrentContext.changeBranch(ScannerContext.BRANCH_IF); - fLocationMap.encounterPoundIf(pound.getOffset(), ident.getOffset(), condEndOffset, endOffset, false, IASTName.EMPTY_NAME_ARRAY); - break; - case IPreprocessorDirective.ppElse: - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - if (fCurrentContext.changeBranch(ScannerContext.BRANCH_ELSE)) { - boolean isActive= nesting == 0 && takeElseBranch; - fLocationMap.encounterPoundElse(pound.getOffset(), ident.getEndOffset(), isActive); - if (isActive) { - return; - } - } - else { - handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, pound.getOffset(), ident.getEndOffset()); - } - break; - case IPreprocessorDirective.ppElif: - if (fCurrentContext.changeBranch(ScannerContext.BRANCH_ELIF)) { - boolean isActive= false; - fExpressionEvaluator.clearMacrosInDefinedExpression(); - int condOffset= lexer.nextToken().getOffset(); - if (nesting == 0 && takeElseBranch) { - TokenList condition= new TokenList(); - condEndOffset= getTokensWithinPPDirective(true, condition, withinExpansion); - if (condition.first() != null) { - try { - isActive= fExpressionEvaluator.evaluate(condition, fMacroDictionary, fLocationMap); - } catch (EvalException e) { - handleProblem(e.getProblemID(), e.getProblemArg(), condOffset, condEndOffset); - } - } - } - else { - condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - } - endOffset= lexer.currentToken().getEndOffset(); - fCurrentContext.changeBranch(ScannerContext.BRANCH_ELIF); - fLocationMap.encounterPoundElif(pound.getOffset(), condOffset, condEndOffset, endOffset, isActive, fExpressionEvaluator.clearMacrosInDefinedExpression()); - - if (isActive) { - return; - } - } - else { - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - endOffset= lexer.currentToken().getEndOffset(); - handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, pound.getOffset(), endOffset); - } - break; - case IPreprocessorDirective.ppEndif: - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - if (fCurrentContext.changeBranch(ScannerContext.BRANCH_END)) { - fLocationMap.encounterPoundEndIf(pound.getOffset(), ident.getEndOffset()); - if (nesting == 0) { - return; - } - --nesting; - } - else { - handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, pound.getOffset(), ident.getEndOffset()); - } - break; - default: - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - break; - } - } - } - + private void skipOverConditionalCode(final Lexer lexer, boolean withinExpansion) throws OffsetLimitReachedException { + CodeState state= CodeState.eSkipInactive; + while (state == CodeState.eSkipInactive) { + state= skipBranch(lexer, withinExpansion); + } + } + + private CodeState skipBranch(final Lexer lexer, boolean withinExpansion) throws OffsetLimitReachedException { + while(true) { + final Token pound = lexer.nextDirective(); + int tt = pound.getType(); + if (tt != IToken.tPOUND) { + if (tt == IToken.tCOMPLETION) { + // completion in inactive code + throw new OffsetLimitReachedException(ORIGIN_INACTIVE_CODE, pound); + } + // must be the end of the lexer + return CodeState.eActive; + } + final Token ident = lexer.nextToken(); + tt = ident.getType(); + if (tt != IToken.tIDENTIFIER) { + if (tt == IToken.tCOMPLETION) { + // completion in inactive directive + throw new OffsetLimitReachedException(ORIGIN_INACTIVE_CODE, ident); + } + lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + continue; + } + + // we have an identifier + final char[] name = ident.getCharImage(); + final int type = fPPKeywords.get(name); + switch (type) { + case IPreprocessorDirective.ppImport: + case IPreprocessorDirective.ppInclude: + executeInclude(lexer, ident.getOffset(), false, false, withinExpansion); + break; + case IPreprocessorDirective.ppInclude_next: + executeInclude(lexer, ident.getOffset(), true, false, withinExpansion); + break; + case IPreprocessorDirective.ppDefine: + executeDefine(lexer, pound.getOffset(), false); + break; + case IPreprocessorDirective.ppIfdef: + return executeIfdef(lexer, pound.getOffset(), false, withinExpansion); + case IPreprocessorDirective.ppIfndef: + return executeIfdef(lexer, pound.getOffset(), true, withinExpansion); + case IPreprocessorDirective.ppIf: + return executeIf(lexer, pound.getOffset(), false, withinExpansion); + case IPreprocessorDirective.ppElif: + return executeIf(lexer, pound.getOffset(), true, withinExpansion); + case IPreprocessorDirective.ppElse: + return executeElse(lexer, pound.getOffset(), withinExpansion); + case IPreprocessorDirective.ppEndif: + return executeEndif(lexer, pound.getOffset(), withinExpansion); + default: + lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + break; + } + } + } + /** * The method assumes that the identifier is consumed. *

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 ea25fb2d703..639b1ee19af 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2009 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 @@ -331,7 +331,7 @@ public class LocationMap implements ILocationResolver { } } - public void encounterPoundDefine(int startOffset, int nameOffset, int nameEndOffset, int expansionOffset, int endOffset, IMacroBinding macrodef) { + public void encounterPoundDefine(int startOffset, int nameOffset, int nameEndOffset, int expansionOffset, int endOffset, boolean isActive, IMacroBinding macrodef) { startOffset= getSequenceNumberForOffset(startOffset); nameOffset= getSequenceNumberForOffset(nameOffset); nameEndOffset= getSequenceNumberForOffset(nameEndOffset); @@ -339,10 +339,10 @@ public class LocationMap implements ILocationResolver { endOffset= getSequenceNumberForOffset(endOffset); ASTPreprocessorNode astMacro; if (!macrodef.isFunctionStyle()) { - astMacro= new ASTMacroDefinition(fTranslationUnit, macrodef, startOffset, nameOffset, nameEndOffset, expansionOffset, endOffset); + astMacro= new ASTMacroDefinition(fTranslationUnit, macrodef, startOffset, nameOffset, nameEndOffset, expansionOffset, endOffset, isActive); } else { - astMacro= new ASTFunctionStyleMacroDefinition(fTranslationUnit, macrodef, startOffset, nameOffset, nameEndOffset, expansionOffset, endOffset); + astMacro= new ASTFunctionStyleMacroDefinition(fTranslationUnit, macrodef, startOffset, nameOffset, nameEndOffset, expansionOffset, endOffset, isActive); } fDirectives.add(astMacro); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java index 71bd0559567..9f49ca4b776 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java @@ -22,17 +22,28 @@ import org.eclipse.cdt.core.parser.OffsetLimitReachedException; final class ScannerContext { private static final Token END_TOKEN = new Token(IToken.tEND_OF_INPUT, null, 0, 0); - public static final Integer BRANCH_IF = new Integer(0); - public static final Integer BRANCH_ELIF = new Integer(1); - public static final Integer BRANCH_ELSE = new Integer(2); - public static final Integer BRANCH_END = new Integer(3); + enum BranchKind {eIf, eElif, eElse, eEnd} + enum CodeState {eActive, eParseInactive, eSkipInactive} + final static class Conditional { + private CodeState fInitialState; + private BranchKind fLast; + private boolean fTakeElse= true; + Conditional(CodeState state) { + fInitialState= state; + fLast= BranchKind.eIf; + } + boolean canHaveActiveBranch(boolean withinExpansion) { + return fTakeElse && (fInitialState == CodeState.eActive || withinExpansion); + } + } + private CodeState fInactiveState= CodeState.eSkipInactive; private final ILocationCtx fLocationCtx; private final ScannerContext fParent; private final Lexer fLexer; - private ArrayList fBranches= null; - private Token fTokens; + private ArrayList fConditionals= null; + private CodeState fCurrentState= CodeState.eActive; /** * @param ctx @@ -49,8 +60,13 @@ final class ScannerContext { fParent= parent; fLexer= null; fTokens= tokens.first(); + fInactiveState= CodeState.eSkipInactive; // no branches in result of macro expansion } + public void setParseInactiveCode(boolean val) { + fInactiveState= val ? CodeState.eParseInactive : CodeState.eSkipInactive; + } + /** * Returns the location context associated with this scanner context. */ @@ -75,35 +91,115 @@ final class ScannerContext { /** * Needs to be called whenever we change over to another branch of conditional - * compilation. Returns whether the change is legal at this point or not. + * compilation. Returns the conditional associated with the branch or null, + * if the change is not legal at this point. */ - public final boolean changeBranch(Integer branchKind) { - if (fBranches == null) { - fBranches= new ArrayList(); + public final Conditional newBranch(BranchKind branchKind, boolean withinExpansion) { + if (fConditionals == null) { + fConditionals= new ArrayList(); } + Conditional result; + // an if starts a new conditional construct - if (branchKind == BRANCH_IF) { - fBranches.add(branchKind); - return true; + if (branchKind == BranchKind.eIf) { + fConditionals.add(result= new Conditional(fCurrentState)); + return result; } + // if we are not inside of an conditional there shouldn't be an #else, #elsif or #end - final int pos= fBranches.size()-1; + final int pos= fConditionals.size()-1; if (pos < 0) { - return false; + return null; } - // an #end just pops one construct. - if (branchKind == BRANCH_END) { - fBranches.remove(pos); - return true; + + // an #end just pops one construct and restores state + if (branchKind == BranchKind.eEnd) { + result= fConditionals.remove(pos); + // implicit state change + changeState(result.fInitialState, withinExpansion); + return result; } - // #elsif or #else cannot appear after another #else - if (fBranches.get(pos) == BRANCH_ELSE) { - return false; + + // #elif or #else cannot appear after another #else + result= fConditionals.get(pos); + if (result.fLast == BranchKind.eElse) + return null; + + // store last kind + result.fLast= branchKind; + return result; + } + + private void changeState(CodeState state, boolean withinExpansion) { + if (!withinExpansion) { + switch (state) { + case eActive: + if (fCurrentState == CodeState.eParseInactive) + stopInactive(); + break; + case eParseInactive: + switch (fCurrentState) { + case eActive: + startInactive(); + break; + case eParseInactive: + separateInactive(); + break; + case eSkipInactive: + assert false; // in macro expansions, only. + break; + } + break; + case eSkipInactive: + // no need to report this to the parser. + break; + } } - // overwrite #if, #elsif with #elsif or #else - fBranches.set(pos, branchKind); - return true; + fCurrentState= state; + } + + private void startInactive() { + if (fTokens != null && fTokens.getType() == IToken.tINACTIVE_CODE_END) { + fTokens= new Token(IToken.tINACTIVE_CODE_SEPARATOR, null, 0, 0); + } else { + fTokens= new Token(IToken.tINACTIVE_CODE_START, null, 0, 0); + } + } + + private void separateInactive() { + if (fTokens == null) { + fTokens= new Token(IToken.tINACTIVE_CODE_SEPARATOR, null, 0, 0); + } + } + + private void stopInactive() { + if (fTokens != null && fTokens.getType() == IToken.tINACTIVE_CODE_START) { + fTokens= null; + } else { + fTokens= new Token(IToken.tINACTIVE_CODE_END, null, 0, 0); + } + } + + public CodeState getCodeState() { + return fCurrentState; + } + + /** + * The preprocessor has to inform the context about the state of if- and elif- branches + */ + public CodeState setBranchState(Conditional cond, boolean isActive, boolean withinExpansion) { + CodeState newState; + if (isActive) { + cond.fTakeElse= false; + newState= cond.fInitialState; + } else if (withinExpansion) { + newState= CodeState.eParseInactive; + } else { + newState= fInactiveState; + } + changeState(newState, withinExpansion); + return newState; } /** @@ -112,12 +208,12 @@ final class ScannerContext { * @since 5.0 */ public final Token currentLexerToken() { - if (fLexer != null) { - return fLexer.currentToken(); - } if (fTokens != null) { return fTokens; } + if (fLexer != null) { + return fLexer.currentToken(); + } return END_TOKEN; } @@ -125,13 +221,14 @@ final class ScannerContext { * Returns the next token from this context. */ public Token nextPPToken() throws OffsetLimitReachedException { + if (fTokens != null) { + fTokens= (Token) fTokens.getNext(); + return currentLexerToken(); + } if (fLexer != null) { return fLexer.nextToken(); } - if (fTokens != null) { - fTokens= (Token) fTokens.getNext(); - } - return currentLexerToken(); + return END_TOKEN; } /** @@ -143,4 +240,8 @@ final class ScannerContext { return fLexer.consumeLine(originPreprocessorDirective); return -1; } + + public void clearInactiveCodeMarkerToken() { + fTokens= null; + } } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/InactiveCodeHighlightingTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/InactiveCodeHighlightingTest.java index 9daaaccad39..f5d646d3468 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/InactiveCodeHighlightingTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/InactiveCodeHighlightingTest.java @@ -126,6 +126,7 @@ public class InactiveCodeHighlightingTest extends TestCase { createPosition(28, 33), createPosition(39, 41), createPosition(47, 57), + createPosition(63, 65), createPosition(67, 69), createPosition(73, 75), }; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/CElementImageProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/CElementImageProvider.java index 7e4969fea46..62d6974d7ce 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/CElementImageProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/CElementImageProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2008 IBM Corporation and others. + * Copyright (c) 2005, 2009 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 @@ -38,6 +38,7 @@ import org.eclipse.cdt.core.model.IInclude; import org.eclipse.cdt.core.model.IIncludeReference; import org.eclipse.cdt.core.model.ILibraryReference; import org.eclipse.cdt.core.model.IMethodDeclaration; +import org.eclipse.cdt.core.model.ISourceReference; import org.eclipse.cdt.core.model.ISourceRoot; import org.eclipse.cdt.core.model.ITemplate; import org.eclipse.cdt.core.model.ITranslationUnit; @@ -457,12 +458,18 @@ public class CElementImageProvider { if(element instanceof ITemplate){ flags |= CElementImageDescriptor.TEMPLATE; } - } else if (element instanceof IInclude) { - IInclude include= (IInclude) element; - if (!include.isActive()) { + } + if (element instanceof ISourceReference) { + ISourceReference sref= (ISourceReference) element; + if (!sref.isActive()) { flags |= CElementImageDescriptor.INACTIVE; - } else if (!include.isResolved()) { - flags |= CElementImageDescriptor.WARNING; + } else { + if (element instanceof IInclude) { + IInclude include= (IInclude) element; + if (!include.isResolved()) { + flags |= CElementImageDescriptor.WARNING; + } + } } } } catch (CModelException e) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/CUILabelProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/CUILabelProvider.java index dcc48e05916..941638740d3 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/CUILabelProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/CUILabelProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2009 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 @@ -23,7 +23,7 @@ import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; -import org.eclipse.cdt.core.model.IInclude; +import org.eclipse.cdt.core.model.ISourceReference; import org.eclipse.cdt.core.model.util.CElementBaseLabels; import org.eclipse.cdt.ui.CUIPlugin; @@ -235,9 +235,9 @@ public class CUILabelProvider extends LabelProvider implements IColorProvider { * @see org.eclipse.jface.viewers.IColorProvider#getForeground(java.lang.Object) */ public Color getForeground(Object element) { - if (element instanceof IInclude) { - IInclude include= (IInclude)element; - if (!include.isActive()) { + if (element instanceof ISourceReference) { + ISourceReference sref= (ISourceReference)element; + if (!sref.isActive()) { if (fInactiveColor == null && Display.getCurrent() != null) { fInactiveColor= CUIPlugin.getStandardDisplay().getSystemColor(SWT.COLOR_DARK_GRAY); fDefaultColor= CUIPlugin.getStandardDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND);