1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Bug 362148: Support for __COUNTER__ macro.

This commit is contained in:
Markus Schorn 2011-11-03 09:25:46 +01:00
parent 09874c7c09
commit 058e14d32c
5 changed files with 88 additions and 11 deletions

View file

@ -354,4 +354,13 @@ public class PreprocessorBugsTests extends PreprocessorTestsBase {
validateIdentifier("B"); validateIdentifier("B");
validateProblemCount(0); validateProblemCount(0);
} }
// __COUNTER__
// __COUNTER__
public void testCounter_Bug362148() throws Exception {
initializeScanner();
validateInteger("0");
validateInteger("1");
validateProblemCount(0);
}
} }

View file

@ -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 __DATE__= new DateMacro("__DATE__".toCharArray()); //$NON-NLS-1$
private static final DynamicMacro __TIME__ = new TimeMacro("__TIME__".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 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$ private static final char[] ONCE = "once".toCharArray(); //$NON-NLS-1$
static final int NO_EXPANSION = 0x01; 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 { private final class MacroDictionary implements IMacroDictionary, ISignificantMacros.IVisitor {
@Override
public boolean satisfies(ISignificantMacros significantMacros) { public boolean satisfies(ISignificantMacros significantMacros) {
return significantMacros.accept(this); return significantMacros.accept(this);
} }
@Override
public boolean visitDefined(char[] macro) { public boolean visitDefined(char[] macro) {
return isDefined(macro); return isDefined(macro);
} }
@Override
public boolean visitUndefined(char[] macro) { public boolean visitUndefined(char[] macro) {
return !isDefined(macro); return !isDefined(macro);
} }
@Override
public boolean visitValue(char[] macro, char[] value) { public boolean visitValue(char[] macro, char[] value) {
PreprocessorMacro m = fMacroDictionary.get(macro); PreprocessorMacro m = fMacroDictionary.get(macro);
return m != null && CharArrayUtils.equals(m.getExpansion(), value); return m != null && CharArrayUtils.equals(m.getExpansion(), value);
@ -141,7 +146,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
} }
final private IIncludeFileTester<InternalFileContent> createCodeReaderTester= new IIncludeFileTester<InternalFileContent>() { final private IIncludeFileTester<InternalFileContent> createCodeReaderTester= new IIncludeFileTester<InternalFileContent>() {
public InternalFileContent checkFile(String path, boolean isHeuristicMatch, IncludeSearchPathElement onPath) { @Override
public InternalFileContent checkFile(String path, boolean isHeuristicMatch, IncludeSearchPathElement onPath) {
final InternalFileContent fc; final InternalFileContent fc;
IFileNomination once= fFileContentProvider.isIncludedWithPragmaOnceSemantics(path); IFileNomination once= fFileContentProvider.isIncludedWithPragmaOnceSemantics(path);
if (once != null) { if (once != null) {
@ -163,7 +169,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
} }
final private IIncludeFileTester<IncludeResolution> createPathTester= new IIncludeFileTester<IncludeResolution>() { final private IIncludeFileTester<IncludeResolution> createPathTester= new IIncludeFileTester<IncludeResolution>() {
public IncludeResolution checkFile(String path, boolean isHeuristicMatch, IncludeSearchPathElement onPath) { @Override
public IncludeResolution checkFile(String path, boolean isHeuristicMatch, IncludeSearchPathElement onPath) {
if (fFileContentProvider.getInclusionExists(path)) { if (fFileContentProvider.getInclusionExists(path)) {
IncludeResolution res= new IncludeResolution(); IncludeResolution res= new IncludeResolution();
res.fHeuristic= isHeuristicMatch; res.fHeuristic= isHeuristicMatch;
@ -181,6 +188,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
fStopAtNewline= stopAtNewline; fStopAtNewline= stopAtNewline;
} }
@Override
public Token nextToken() throws OffsetLimitReachedException { public Token nextToken() throws OffsetLimitReachedException {
final Lexer lexer= fCurrentContext.getLexer(); final Lexer lexer= fCurrentContext.getLexer();
Token t= lexer.nextToken(); Token t= lexer.nextToken();
@ -194,10 +202,12 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
return t; return t;
} }
@Override
public int getLastEndOffset() { public int getLastEndOffset() {
return fCurrentContext.getLexer().getLastEndOffset(); return fCurrentContext.getLexer().getLastEndOffset();
} }
@Override
public Token currentToken() { public Token currentToken() {
Token t= fCurrentContext.currentLexerToken(); Token t= fCurrentContext.currentLexerToken();
if (fStopAtNewline && t.getType() == Lexer.tNEWLINE) if (fStopAtNewline && t.getType() == Lexer.tNEWLINE)
@ -323,14 +333,17 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
return null; return null;
} }
@Override
public void setSplitShiftROperator(boolean val) { public void setSplitShiftROperator(boolean val) {
fSplitShiftRightOperator= val; fSplitShiftRightOperator= val;
} }
@Override
public void setComputeImageLocations(boolean val) { public void setComputeImageLocations(boolean val) {
fLexOptions.fCreateImageLocations= val; fLexOptions.fCreateImageLocations= val;
} }
@Override
public void setContentAssistMode(int offset) { public void setContentAssistMode(int offset) {
fContentAssistLimit= offset; fContentAssistLimit= offset;
fRootLexer.setContentAssistMode(offset); fRootLexer.setContentAssistMode(offset);
@ -340,13 +353,16 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
return fRootLexer.isContentAssistMode(); return fRootLexer.isContentAssistMode();
} }
@Override
public void setProcessInactiveCode(boolean val) { public void setProcessInactiveCode(boolean val) {
fRootContext.setParseInactiveCode(val); fRootContext.setParseInactiveCode(val);
} }
@Override
public void setScanComments(boolean val) { public void setScanComments(boolean val) {
} }
@Override
public ILocationResolver getLocationResolver() { public ILocationResolver getLocationResolver() {
return fLocationMap; return fLocationMap;
} }
@ -413,7 +429,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
fMacroDictionary.put(__DATE__.getNameCharArray(), __DATE__); fMacroDictionary.put(__DATE__.getNameCharArray(), __DATE__);
fMacroDictionary.put(__TIME__.getNameCharArray(), __TIME__); fMacroDictionary.put(__TIME__.getNameCharArray(), __TIME__);
fMacroDictionary.put(__LINE__.getNameCharArray(), __LINE__); fMacroDictionary.put(__LINE__.getNameCharArray(), __LINE__);
fMacroDictionary.put(__COUNTER__, new CounterMacro(__COUNTER__));
if (lang == ParserLanguage.CPP) { if (lang == ParserLanguage.CPP) {
fMacroDictionary.put(__cplusplus.getNameCharArray(), __cplusplus); fMacroDictionary.put(__cplusplus.getNameCharArray(), __cplusplus);
} else { } else {
@ -520,7 +537,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
} }
} }
public Map<String, IMacroBinding> getMacroDefinitions() { @Override
public Map<String, IMacroBinding> getMacroDefinitions() {
Map<String, IMacroBinding> hashMap = new HashMap<String, IMacroBinding>(fMacroDictionary.size()); Map<String, IMacroBinding> hashMap = new HashMap<String, IMacroBinding>(fMacroDictionary.size());
for (char[] key : fMacroDictionary.keys()) { for (char[] key : fMacroDictionary.keys()) {
hashMap.put(String.valueOf(key), fMacroDictionary.get(key)); hashMap.put(String.valueOf(key), fMacroDictionary.get(key));
@ -528,7 +546,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
return hashMap; return hashMap;
} }
public boolean isOnTopContext() { @Override
public boolean isOnTopContext() {
ScannerContext ctx= fCurrentContext; ScannerContext ctx= fCurrentContext;
while (ctx != null && ctx.getLocationCtx() instanceof LocationCtxMacroExpansion) { while (ctx != null && ctx.getLocationCtx() instanceof LocationCtxMacroExpansion) {
ctx= ctx.getParent(); ctx= ctx.getParent();
@ -536,7 +555,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
return ctx == fRootContext; return ctx == fRootContext;
} }
public void cancel() { @Override
public void cancel() {
isCancelled= true; 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 EndOfFileException when the end of the translation unit has been reached.
* @throws OffsetLimitReachedException see {@link Lexer}. * @throws OffsetLimitReachedException see {@link Lexer}.
*/ */
public IToken nextToken() throws EndOfFileException { @Override
public IToken nextToken() throws EndOfFileException {
if (isCancelled) { if (isCancelled) {
throw new ParseError(ParseError.ParseErrorKind.TIMEOUT_OR_CANCELLED); throw new ParseError(ParseError.ParseErrorKind.TIMEOUT_OR_CANCELLED);
} }
@ -746,7 +767,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
return t1; return t1;
} }
public void skipInactiveCode() throws OffsetLimitReachedException { @Override
public void skipInactiveCode() throws OffsetLimitReachedException {
final Lexer lexer= fCurrentContext.getLexer(); final Lexer lexer= fCurrentContext.getLexer();
if (lexer != null) { if (lexer != null) {
CodeState state= fCurrentContext.getCodeState(); CodeState state= fCurrentContext.getCodeState();
@ -758,6 +780,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
} }
@Override
public int getCodeBranchNesting() { public int getCodeBranchNesting() {
return fCurrentContext.getCodeBranchNesting(); return fCurrentContext.getCodeBranchNesting();
} }
@ -1142,11 +1165,13 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
return fLocationMap; return fLocationMap;
} }
@Override
public void handleComment(boolean isBlockComment, int offset, int endOffset) { public void handleComment(boolean isBlockComment, int offset, int endOffset) {
fLocationMap.encounteredComment(offset, endOffset, isBlockComment); 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); fLocationMap.encounterProblem(id, arg, offset, endOffset);
} }
@ -1856,6 +1881,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
return true; return true;
} }
@Override
@SuppressWarnings({ "rawtypes", "unchecked" }) @SuppressWarnings({ "rawtypes", "unchecked" })
public Object getAdapter(Class adapter) { public Object getAdapter(Class adapter) {
if (adapter.isAssignableFrom(fMacroExpander.getClass())) { if (adapter.isAssignableFrom(fMacroExpander.getClass())) {

View file

@ -12,8 +12,6 @@ package org.eclipse.cdt.internal.core.parser.scanner;
import java.util.Calendar; import java.util.Calendar;
import com.ibm.icu.text.DateFormatSymbols;
import org.eclipse.cdt.core.dom.ILinkage; import org.eclipse.cdt.core.dom.ILinkage;
import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IMacroBinding; import org.eclipse.cdt.core.dom.ast.IMacroBinding;
@ -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.dom.Linkage;
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions; import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
import com.ibm.icu.text.DateFormatSymbols;
/** /**
* Models macros used by the preprocessor * Models macros used by the preprocessor
* @since 5.0 * @since 5.0
@ -35,38 +35,47 @@ abstract class PreprocessorMacro implements IMacroBinding {
fName= name; fName= name;
} }
@Override
final public ILinkage getLinkage() { final public ILinkage getLinkage() {
return Linkage.NO_LINKAGE; return Linkage.NO_LINKAGE;
} }
@Override
final public char[] getNameCharArray() { final public char[] getNameCharArray() {
return fName; return fName;
} }
@Override
final public String getName() { final public String getName() {
return new String(fName); return new String(fName);
} }
@Override
public IScope getScope() { public IScope getScope() {
return null; return null;
} }
@Override
public IBinding getOwner() { public IBinding getOwner() {
return null; return null;
} }
@Override
public boolean isFunctionStyle() { public boolean isFunctionStyle() {
return false; return false;
} }
@Override
public char[][] getParameterList() { public char[][] getParameterList() {
return null; return null;
} }
@Override
public char[][] getParameterPlaceholderList() { public char[][] getParameterPlaceholderList() {
return null; return null;
} }
@Override
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
public Object getAdapter(Class clazz) { public Object getAdapter(Class clazz) {
return null; return null;
@ -139,10 +148,12 @@ class ObjectStyleMacro extends PreprocessorMacro {
} }
} }
@Override
public char[] getExpansion() { public char[] getExpansion() {
return MacroDefinitionParser.getExpansion(fExpansion, fExpansionOffset, fEndOffset); return MacroDefinitionParser.getExpansion(fExpansion, fExpansionOffset, fEndOffset);
} }
@Override
public char[] getExpansionImage() { public char[] getExpansionImage() {
final int length = fEndOffset - fExpansionOffset; final int length = fEndOffset - fExpansionOffset;
char[] result= new char[length]; char[] result= new char[length];
@ -164,6 +175,7 @@ class ObjectStyleMacro extends PreprocessorMacro {
return fExpansionTokens; return fExpansionTokens;
} }
@Override
public final boolean isDynamic() { public final boolean isDynamic() {
return false; return false;
} }
@ -283,14 +295,17 @@ final class UndefinedMacro extends PreprocessorMacro {
return null; return null;
} }
@Override
public char[] getExpansion() { public char[] getExpansion() {
return null; return null;
} }
@Override
public char[] getExpansionImage() { public char[] getExpansionImage() {
return null; return null;
} }
@Override
public boolean isDynamic() { public boolean isDynamic() {
return false; return false;
} }
@ -301,6 +316,7 @@ abstract class DynamicMacro extends PreprocessorMacro {
public DynamicMacro(char[] name) { public DynamicMacro(char[] name) {
super(name); super(name);
} }
@Override
public final char[] getExpansion() { public final char[] getExpansion() {
return getExpansionImage(); return getExpansionImage();
} }
@ -319,6 +335,7 @@ abstract class DynamicMacro extends PreprocessorMacro {
buffer.append(value); buffer.append(value);
} }
@Override
public final boolean isDynamic() { public final boolean isDynamic() {
return true; return true;
} }
@ -349,6 +366,7 @@ final class DateMacro extends DynamicMacro {
return charArray; return charArray;
} }
@Override
public char[] getExpansionImage() { public char[] getExpansionImage() {
return createDate(); return createDate();
} }
@ -367,6 +385,7 @@ final class FileMacro extends DynamicMacro {
return new TokenWithImage(IToken.tSTRING, null, 0, 0, buffer.toString().toCharArray()); return new TokenWithImage(IToken.tSTRING, null, 0, 0, buffer.toString().toCharArray());
} }
@Override
public char[] getExpansionImage() { public char[] getExpansionImage() {
return "\"file\"".toCharArray(); //$NON-NLS-1$ 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()); return new TokenWithImage(IToken.tINTEGER, null, 0, 0, Long.toString(lineNumber).toCharArray());
} }
@Override
public char[] getExpansionImage() { public char[] getExpansionImage() {
return new char[] {'1'}; return new char[] {'1'};
} }
@ -410,7 +430,27 @@ final class TimeMacro extends DynamicMacro {
return buffer.toString().toCharArray(); return buffer.toString().toCharArray();
} }
@Override
public char[] getExpansionImage() { public char[] getExpansionImage() {
return createDate(); 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;
}
}

View file

@ -31,6 +31,7 @@ public class CompletionTest_MacroRef_NoPrefix extends CompletionProposalsBaseTe
"DEBUG", "DEBUG",
"XMacro(x, y)", "XMacro(x, y)",
"__CDT_PARSER__", "__CDT_PARSER__",
"__COUNTER__",
"__DATE__", "__DATE__",
"__FILE__", "__FILE__",
"__LINE__", "__LINE__",

View file

@ -358,6 +358,7 @@ public class CompletionTests_PlainC extends AbstractContentAssistTest {
"DEBUG", "DEBUG",
"XMacro(x, y)", "XMacro(x, y)",
"__CDT_PARSER__", "__CDT_PARSER__",
"__COUNTER__",
"__DATE__", "__DATE__",
"__FILE__", "__FILE__",
"__LINE__", "__LINE__",