diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorBugsTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorBugsTests.java index 53d7b10d6d6..cbc7925b4d0 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorBugsTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorBugsTests.java @@ -354,4 +354,13 @@ public class PreprocessorBugsTests extends PreprocessorTestsBase { validateIdentifier("B"); validateProblemCount(0); } + + // __COUNTER__ + // __COUNTER__ + public void testCounter_Bug362148() throws Exception { + initializeScanner(); + validateInteger("0"); + validateInteger("1"); + validateProblemCount(0); + } } 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 3b3eeb9d3c4..0cd5d9e9944 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 @@ -99,6 +99,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { private static final DynamicMacro __DATE__= new DateMacro("__DATE__".toCharArray()); //$NON-NLS-1$ private static final DynamicMacro __TIME__ = new TimeMacro("__TIME__".toCharArray()); //$NON-NLS-1$ private static final DynamicMacro __LINE__ = new LineMacro("__LINE__".toCharArray()); //$NON-NLS-1$ + private static final char[] __COUNTER__ = "__COUNTER__".toCharArray(); //$NON-NLS-1$ private static final char[] ONCE = "once".toCharArray(); //$NON-NLS-1$ static final int NO_EXPANSION = 0x01; @@ -114,18 +115,22 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { private final class MacroDictionary implements IMacroDictionary, ISignificantMacros.IVisitor { + @Override public boolean satisfies(ISignificantMacros significantMacros) { return significantMacros.accept(this); } + @Override public boolean visitDefined(char[] macro) { return isDefined(macro); } + @Override public boolean visitUndefined(char[] macro) { return !isDefined(macro); } + @Override public boolean visitValue(char[] macro, char[] value) { PreprocessorMacro m = fMacroDictionary.get(macro); return m != null && CharArrayUtils.equals(m.getExpansion(), value); @@ -141,7 +146,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } final private IIncludeFileTester createCodeReaderTester= new IIncludeFileTester() { - public InternalFileContent checkFile(String path, boolean isHeuristicMatch, IncludeSearchPathElement onPath) { + @Override + public InternalFileContent checkFile(String path, boolean isHeuristicMatch, IncludeSearchPathElement onPath) { final InternalFileContent fc; IFileNomination once= fFileContentProvider.isIncludedWithPragmaOnceSemantics(path); if (once != null) { @@ -163,7 +169,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } final private IIncludeFileTester createPathTester= new IIncludeFileTester() { - public IncludeResolution checkFile(String path, boolean isHeuristicMatch, IncludeSearchPathElement onPath) { + @Override + public IncludeResolution checkFile(String path, boolean isHeuristicMatch, IncludeSearchPathElement onPath) { if (fFileContentProvider.getInclusionExists(path)) { IncludeResolution res= new IncludeResolution(); res.fHeuristic= isHeuristicMatch; @@ -181,6 +188,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { fStopAtNewline= stopAtNewline; } + @Override public Token nextToken() throws OffsetLimitReachedException { final Lexer lexer= fCurrentContext.getLexer(); Token t= lexer.nextToken(); @@ -194,10 +202,12 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { return t; } + @Override public int getLastEndOffset() { return fCurrentContext.getLexer().getLastEndOffset(); } + @Override public Token currentToken() { Token t= fCurrentContext.currentLexerToken(); if (fStopAtNewline && t.getType() == Lexer.tNEWLINE) @@ -323,14 +333,17 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { return null; } + @Override public void setSplitShiftROperator(boolean val) { fSplitShiftRightOperator= val; } + @Override public void setComputeImageLocations(boolean val) { fLexOptions.fCreateImageLocations= val; } + @Override public void setContentAssistMode(int offset) { fContentAssistLimit= offset; fRootLexer.setContentAssistMode(offset); @@ -340,13 +353,16 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { return fRootLexer.isContentAssistMode(); } + @Override public void setProcessInactiveCode(boolean val) { fRootContext.setParseInactiveCode(val); } + @Override public void setScanComments(boolean val) { } + @Override public ILocationResolver getLocationResolver() { return fLocationMap; } @@ -413,7 +429,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { fMacroDictionary.put(__DATE__.getNameCharArray(), __DATE__); fMacroDictionary.put(__TIME__.getNameCharArray(), __TIME__); fMacroDictionary.put(__LINE__.getNameCharArray(), __LINE__); - + fMacroDictionary.put(__COUNTER__, new CounterMacro(__COUNTER__)); + if (lang == ParserLanguage.CPP) { fMacroDictionary.put(__cplusplus.getNameCharArray(), __cplusplus); } else { @@ -520,7 +537,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } } - public Map getMacroDefinitions() { + @Override + public Map getMacroDefinitions() { Map hashMap = new HashMap(fMacroDictionary.size()); for (char[] key : fMacroDictionary.keys()) { hashMap.put(String.valueOf(key), fMacroDictionary.get(key)); @@ -528,7 +546,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { return hashMap; } - public boolean isOnTopContext() { + @Override + public boolean isOnTopContext() { ScannerContext ctx= fCurrentContext; while (ctx != null && ctx.getLocationCtx() instanceof LocationCtxMacroExpansion) { ctx= ctx.getParent(); @@ -536,7 +555,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { return ctx == fRootContext; } - public void cancel() { + @Override + public void cancel() { isCancelled= true; } @@ -648,7 +668,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { * @throws EndOfFileException when the end of the translation unit has been reached. * @throws OffsetLimitReachedException see {@link Lexer}. */ - public IToken nextToken() throws EndOfFileException { + @Override + public IToken nextToken() throws EndOfFileException { if (isCancelled) { throw new ParseError(ParseError.ParseErrorKind.TIMEOUT_OR_CANCELLED); } @@ -746,7 +767,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { return t1; } - public void skipInactiveCode() throws OffsetLimitReachedException { + @Override + public void skipInactiveCode() throws OffsetLimitReachedException { final Lexer lexer= fCurrentContext.getLexer(); if (lexer != null) { CodeState state= fCurrentContext.getCodeState(); @@ -758,6 +780,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } + @Override public int getCodeBranchNesting() { return fCurrentContext.getCodeBranchNesting(); } @@ -1142,11 +1165,13 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { return fLocationMap; } + @Override public void handleComment(boolean isBlockComment, int offset, int endOffset) { fLocationMap.encounteredComment(offset, endOffset, isBlockComment); } - public void handleProblem(int id, char[] arg, int offset, int endOffset) { + @Override + public void handleProblem(int id, char[] arg, int offset, int endOffset) { fLocationMap.encounterProblem(id, arg, offset, endOffset); } @@ -1856,6 +1881,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { return true; } + @Override @SuppressWarnings({ "rawtypes", "unchecked" }) public Object getAdapter(Class adapter) { if (adapter.isAssignableFrom(fMacroExpander.getClass())) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/PreprocessorMacro.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/PreprocessorMacro.java index 1892182f2d1..ed108f621c8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/PreprocessorMacro.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/PreprocessorMacro.java @@ -12,8 +12,6 @@ package org.eclipse.cdt.internal.core.parser.scanner; import java.util.Calendar; -import com.ibm.icu.text.DateFormatSymbols; - import org.eclipse.cdt.core.dom.ILinkage; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IMacroBinding; @@ -24,6 +22,8 @@ import org.eclipse.cdt.core.parser.OffsetLimitReachedException; import org.eclipse.cdt.internal.core.dom.Linkage; import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions; +import com.ibm.icu.text.DateFormatSymbols; + /** * Models macros used by the preprocessor * @since 5.0 @@ -35,38 +35,47 @@ abstract class PreprocessorMacro implements IMacroBinding { fName= name; } + @Override final public ILinkage getLinkage() { return Linkage.NO_LINKAGE; } + @Override final public char[] getNameCharArray() { return fName; } + @Override final public String getName() { return new String(fName); } + @Override public IScope getScope() { return null; } + @Override public IBinding getOwner() { return null; } + @Override public boolean isFunctionStyle() { return false; } + @Override public char[][] getParameterList() { return null; } + @Override public char[][] getParameterPlaceholderList() { return null; } + @Override @SuppressWarnings("rawtypes") public Object getAdapter(Class clazz) { return null; @@ -139,10 +148,12 @@ class ObjectStyleMacro extends PreprocessorMacro { } } + @Override public char[] getExpansion() { return MacroDefinitionParser.getExpansion(fExpansion, fExpansionOffset, fEndOffset); } + @Override public char[] getExpansionImage() { final int length = fEndOffset - fExpansionOffset; char[] result= new char[length]; @@ -164,6 +175,7 @@ class ObjectStyleMacro extends PreprocessorMacro { return fExpansionTokens; } + @Override public final boolean isDynamic() { return false; } @@ -283,14 +295,17 @@ final class UndefinedMacro extends PreprocessorMacro { return null; } + @Override public char[] getExpansion() { return null; } + @Override public char[] getExpansionImage() { return null; } + @Override public boolean isDynamic() { return false; } @@ -301,6 +316,7 @@ abstract class DynamicMacro extends PreprocessorMacro { public DynamicMacro(char[] name) { super(name); } + @Override public final char[] getExpansion() { return getExpansionImage(); } @@ -319,6 +335,7 @@ abstract class DynamicMacro extends PreprocessorMacro { buffer.append(value); } + @Override public final boolean isDynamic() { return true; } @@ -349,6 +366,7 @@ final class DateMacro extends DynamicMacro { return charArray; } + @Override public char[] getExpansionImage() { return createDate(); } @@ -367,6 +385,7 @@ final class FileMacro extends DynamicMacro { return new TokenWithImage(IToken.tSTRING, null, 0, 0, buffer.toString().toCharArray()); } + @Override public char[] getExpansionImage() { return "\"file\"".toCharArray(); //$NON-NLS-1$ } @@ -383,6 +402,7 @@ final class LineMacro extends DynamicMacro { return new TokenWithImage(IToken.tINTEGER, null, 0, 0, Long.toString(lineNumber).toCharArray()); } + @Override public char[] getExpansionImage() { return new char[] {'1'}; } @@ -410,7 +430,27 @@ final class TimeMacro extends DynamicMacro { return buffer.toString().toCharArray(); } + @Override public char[] getExpansionImage() { return createDate(); } } + +final class CounterMacro extends DynamicMacro { + private static final char[] ZERO = {'0'}; + + private long fValue= 0; + CounterMacro(char[] name) { + super(name); + } + + @Override + public Token execute(MacroExpander expander) { + return new TokenWithImage(IToken.tINTEGER, null, 0, 0, String.valueOf(fValue++).toCharArray()); + } + + @Override + public char[] getExpansionImage() { + return ZERO; + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTest_MacroRef_NoPrefix.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTest_MacroRef_NoPrefix.java index 617415884cd..cc92fda5385 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTest_MacroRef_NoPrefix.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTest_MacroRef_NoPrefix.java @@ -31,6 +31,7 @@ public class CompletionTest_MacroRef_NoPrefix extends CompletionProposalsBaseTe "DEBUG", "XMacro(x, y)", "__CDT_PARSER__", + "__COUNTER__", "__DATE__", "__FILE__", "__LINE__", diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTests_PlainC.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTests_PlainC.java index 44823cfe330..b5da4972d4c 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTests_PlainC.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTests_PlainC.java @@ -358,6 +358,7 @@ public class CompletionTests_PlainC extends AbstractContentAssistTest { "DEBUG", "XMacro(x, y)", "__CDT_PARSER__", + "__COUNTER__", "__DATE__", "__FILE__", "__LINE__",