From 981ddadee087d6bb6a27260c019df97e6e40f373 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Tue, 6 Nov 2007 16:53:51 +0000 Subject: [PATCH] Parser tests using CPreprocessor --- .../cdt/core/dom/ast/ASTSignatureUtil.java | 12 +- .../cdt/core/dom/ast/IASTFileLocation.java | 10 + .../cdt/core/dom/ast/IASTMacroExpansion.java | 25 +- .../cdt/core/dom/ast/IASTNodeLocation.java | 11 +- .../cdt/core/dom/ast/IASTTranslationUnit.java | 26 +- .../cdt/core/parser/util/CharArrayIntMap.java | 2 +- .../cdt/internal/core/dom/parser/ASTNode.java | 34 ++- .../parser/AbstractGNUSourceCodeParser.java | 9 +- .../dom/parser/c/CASTTranslationUnit.java | 61 ++-- .../dom/parser/cpp/CPPASTTranslationUnit.java | 43 ++- .../dom/parser/cpp/GNUCPPSourceParser.java | 30 +- .../parser/scanner/ASTPreprocessorNode.java | 106 ++++++- .../core/parser/scanner/CPreprocessor.java | 85 +++--- .../parser/scanner/ExpressionEvaluator.java | 2 +- .../parser/scanner/ILocationResolver.java | 50 +++- .../internal/core/parser/scanner/Lexer.java | 19 +- .../core/parser/scanner/LocationCtx.java | 265 ++---------------- .../parser/scanner/LocationCtxContainer.java | 220 +++++++++++++++ .../core/parser/scanner/LocationCtxFile.java | 93 ++++++ .../scanner/LocationCtxMacroExpansion.java | 57 ++++ .../core/parser/scanner/LocationMap.java | 166 +++++++---- .../parser/scanner/MacroDefinitionParser.java | 28 +- .../core/parser/scanner/MacroExpander.java | 15 +- .../scanner/ScannerContextMacroExpansion.java | 2 +- .../scanner/ScannerContextPPDirective.java | 2 +- .../internal/core/parser/scanner/Token.java | 86 +----- .../core/parser/scanner/TokenForDigraph.java | 25 ++ .../core/parser/scanner/TokenWithImage.java | 24 ++ .../core/parser/token/TokenFactory.java | 127 ++++++++- 29 files changed, 1110 insertions(+), 525 deletions(-) create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxContainer.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxFile.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxMacroExpansion.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenForDigraph.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenWithImage.java diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTSignatureUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTSignatureUtil.java index d7c64d10a27..9419ed8c90e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTSignatureUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTSignatureUtil.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005 IBM Corporation and others. + * Copyright (c) 2005, 2007 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 @@ -7,6 +7,7 @@ * * Contributors: * Rational Software - initial implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.dom.ast; @@ -724,9 +725,14 @@ public class ASTSignatureUtil { private static String getLiteralExpression( IASTLiteralExpression expression ){ StringBuffer result = new StringBuffer(); - if (expression.getKind() == IASTLiteralExpression.lk_string_literal) result.append("\""); //$NON-NLS-1$ result.append(expression.toString()); - if (expression.getKind() == IASTLiteralExpression.lk_string_literal) result.append("\""); //$NON-NLS-1$ + if (expression.getKind() == IASTLiteralExpression.lk_string_literal) { + // mstodo- support for old scanner + if (result.length() == 0 || result.charAt(0) != '"') { + result.insert(0, '"'); + result.append('"'); + } + } return result.toString(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTFileLocation.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTFileLocation.java index c79109aea54..604bc4257fc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTFileLocation.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTFileLocation.java @@ -24,6 +24,16 @@ public interface IASTFileLocation extends IASTNodeLocation { */ public String getFileName(); + /** + * Returns the offset within the file where this location starts. + */ + public int getNodeOffset(); + + /** + * Returns the length of this location in terms of characters. + */ + public int getNodeLength(); + /** * Get the starting line number. Locations obtained via the index do not have line numbers * and return 0. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTMacroExpansion.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTMacroExpansion.java index bd77d82fa56..0500a5e9cab 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTMacroExpansion.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTMacroExpansion.java @@ -1,12 +1,13 @@ /******************************************************************************* - * Copyright (c) 2004, 2005 IBM Corporation and others. + * Copyright (c) 2004, 2007 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 * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation + * IBM - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.dom.ast; @@ -26,14 +27,26 @@ public interface IASTMacroExpansion extends IASTNodeLocation { */ public IASTPreprocessorMacroDefinition getMacroDefinition(); + /** + * Returns an offset within the macro-expansion. The offset can be used to compare + * nodes within the same macro-expansion. However, it does not serve as an offset + * into a file. + */ + public int getNodeOffset(); + + /** + * Returns the length of this location. The length can be used to compare this location + * with others from within the same macro-expansion. However, the length does not neccessarily + * relate to a length in terms of characters. + */ + public int getNodeLength(); + /** * The source locations for for the macro expansion. These are the locations - * where the expansion in question occured and was replaced. + * where the expansion in question occurred and was replaced. * * @return + * @deprecated use {@link IASTNodeLocation#asFileLocation()}. */ public IASTNodeLocation[] getExpansionLocations(); - - - } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNodeLocation.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNodeLocation.java index 252848c383f..6ea284d8085 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNodeLocation.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNodeLocation.java @@ -19,24 +19,17 @@ package org.eclipse.cdt.core.dom.ast; public interface IASTNodeLocation { /** - * This is the offset into the actual source location that this node starts - * at. - * - * @return + * This is the offset within either the file or a macro-expansion. */ public int getNodeOffset(); /** - * This is the length of the node contained in this location. - * - * @return + * This is the length of the node within the file or macro-expansion. */ public int getNodeLength(); /** * Return a file location that best maps into this location. - * - * @return */ public IASTFileLocation asFileLocation(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java index e96bd84df13..064e0373b80 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTranslationUnit.java @@ -6,21 +6,22 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation - * Markus Schorn (Wind River Systems) + * IBM - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.dom.ast; import org.eclipse.cdt.core.dom.IName; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.parser.ParserLanguage; +import org.eclipse.core.runtime.IAdaptable; /** * The translation unit represents a compilable unit of source. * * @author Doug Schaefer */ -public interface IASTTranslationUnit extends IASTNode { +public interface IASTTranslationUnit extends IASTNode, IAdaptable { /** * OWNED_DECLARATION represents the relationship between an IASTTranslationUnit and @@ -115,12 +116,25 @@ public interface IASTTranslationUnit extends IASTNode { public IASTName[] getReferences(IBinding binding); /** - * @param offset + * Returns an array of locations. This is a sequence of file locations and macro-expansion locations. + * @param offset sequence number as stored in the ast nodes. * @param length - * @return + * @return and array of locations. */ public IASTNodeLocation[] getLocationInfo(int offset, int length); + /** + * Returns the smallest file location, that encloses the given global range. In case the range + * spans over multiple files, the files are mapped to include statements until all of them are + * found in the same file. So the resulting location contains the include directives that actually + * cause the range to be part of the AST. + * @param offset sequence number as stored in the ASTNodes. + * @param length + * @return a file location + * @since 5.0 + */ + public IASTFileLocation getMappedFileLocation(int offset, int length); + /** * Select the node in the treet that best fits the offset/length/file path. * @@ -173,6 +187,7 @@ public interface IASTTranslationUnit extends IASTNode { * * @param locations A range of node locations * @return A String signature. + * @deprecated was never fully implemented. */ public String getUnpreprocessedSignature(IASTNodeLocation[] locations); @@ -187,6 +202,7 @@ public interface IASTTranslationUnit extends IASTNode { * * @param nodeLocations IASTNodeLocations to flatten * @return null if not possible, otherwise, a file location representing where the macros are. + * @deprecated use {@link #getMappedFileLocation(int, int)} */ public IASTFileLocation flattenLocationsToFile( IASTNodeLocation [] nodeLocations ); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CharArrayIntMap.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CharArrayIntMap.java index 605ae4df9fc..71925d49e1c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CharArrayIntMap.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CharArrayIntMap.java @@ -85,7 +85,7 @@ public class CharArrayIntMap extends CharTable { */ public void putAll(CharArrayIntMap map) { resize(size() + map.size()); - for(int i=0; i 2 && assemblyChars[0] == '"') { + assembly= new String(assemblyChars, 1, assemblyChars.length-2); + } + else { + assembly= new String(assemblyChars); + } consume(IToken.tRPAREN); int lastOffset = consume(IToken.tSEMI).getEndOffset(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTTranslationUnit.java index 40f6bf2aab1..4453281e843 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTTranslationUnit.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTTranslationUnit.java @@ -6,9 +6,9 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM Rational Software - Initial API and implementation - * Markus Schorn (Wind River Systems) - * Yuan Zhang / Beth Tibbitts (IBM Research) + * IBM Rational Software - Initial API and implementation + * Markus Schorn (Wind River Systems) + * Yuan Zhang / Beth Tibbitts (IBM Research) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.c; @@ -391,8 +391,25 @@ public class CASTTranslationUnit extends CASTNode implements * * @see org.eclipse.cdt.core.dom.ast.IASTTranslationUnit#getNodeForLocation(org.eclipse.cdt.core.dom.ast.IASTNodeLocation) */ - public IASTNode selectNodeForLocation(String path, int realOffset, - int realLength) { + public IASTNode selectNodeForLocation(String path, int realOffset, int realLength) { + if (resolver instanceof org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) { + org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver r2= (org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) resolver; + IASTNode result= null; + int start= r2.getSequenceNumberForFileOffset(path, realOffset); + if (start >= 0) { + int length= realLength < 1 ? 0 : + r2.getSequenceNumberForFileOffset(path, realOffset+realLength-1) + 1 - start; + result= r2.findSurroundingPreprocessorNode(start, length); + if (result == null) { + CFindNodeForOffsetAction nodeFinder = new CFindNodeForOffsetAction(start, length); + accept(nodeFinder); + result = nodeFinder.getNode(); + } + } + return result; + } + + // mstodo- support for old location resolver IASTNode node = null; ASTPreprocessorSelectionResult result = null; int globalOffset = 0; @@ -480,17 +497,6 @@ public class CASTTranslationUnit extends CASTNode implements resolver.setRootNode( this ); } - /* - * (non-Javadoc) - * - * @see java.lang.Object#finalize() - */ - protected void finalize() throws Throwable { - if (resolver != null) - resolver.cleanup(); - super.finalize(); - } - /* * (non-Javadoc) * @@ -552,7 +558,15 @@ public class CASTTranslationUnit extends CASTNode implements return true; } - public IASTFileLocation flattenLocationsToFile(IASTNodeLocation[] nodeLocations) { + public IASTFileLocation getMappedFileLocation(int offset, int length) { + if (resolver instanceof org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) { + org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver r2= (org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) resolver; + return r2.getMappedFileLocation(offset, length); + } + return flattenLocationsToFile(getLocationInfo(offset, length)); + } + + public IASTFileLocation flattenLocationsToFile(IASTNodeLocation[] nodeLocations) { if( resolver == null ) return null; return resolver.flattenLocations( nodeLocations ); @@ -590,11 +604,22 @@ public class CASTTranslationUnit extends CASTNode implements } public IASTComment[] getComments() { + if (resolver instanceof org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) { + org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver r2= (org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) resolver; + return r2.getComments(); + } + // support for old location resolver return comments; } public void setComments(IASTComment[] comments) { this.comments = comments; } - + + public Object getAdapter(Class adapter) { + if (adapter.isAssignableFrom(resolver.getClass())) { + return resolver; + } + return null; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java index ff552ef57a8..d0f75de4e28 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java @@ -6,8 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation - * Markus Schorn (Wind River Systems) + * IBM - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -382,6 +382,24 @@ public class CPPASTTranslationUnit extends CPPASTNode implements public IASTNode selectNodeForLocation(String path, int realOffset, int realLength) { + if (resolver instanceof org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) { + org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver r2= (org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) resolver; + IASTNode result= null; + int start= r2.getSequenceNumberForFileOffset(path, realOffset); + if (start >= 0) { + int length= realLength < 1 ? 0 : + r2.getSequenceNumberForFileOffset(path, realOffset+realLength-1) + 1 - start; + result= r2.findSurroundingPreprocessorNode(start, length); + if (result == null) { + CPPFindNodeForOffsetAction nodeFinder = new CPPFindNodeForOffsetAction(start, length); + accept(nodeFinder); + result = nodeFinder.getNode(); + } + } + return result; + } + + // mstodo- support for old location resolver IASTNode node = null; ASTPreprocessorSelectionResult result = null; int globalOffset = 0; @@ -491,6 +509,14 @@ public class CPPASTTranslationUnit extends CPPASTNode implements return true; } + public IASTFileLocation getMappedFileLocation(int offset, int length) { + if (resolver instanceof org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) { + org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver r2= (org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) resolver; + return r2.getMappedFileLocation(offset, length); + } + return flattenLocationsToFile(getLocationInfo(offset, length)); + } + public IASTFileLocation flattenLocationsToFile(IASTNodeLocation[] nodeLocations) { if( resolver == null ) return null; @@ -542,11 +568,22 @@ public class CPPASTTranslationUnit extends CPPASTNode implements } public IASTComment[] getComments() { + if (resolver instanceof org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) { + org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver r2= (org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) resolver; + return r2.getComments(); + } + // support for old location resolver return comments; } public void setComments(IASTComment[] comments) { this.comments = comments; } - + + public Object getAdapter(Class adapter) { + if (adapter.isAssignableFrom(resolver.getClass())) { + return resolver; + } + return null; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java index b30c4d9e209..ee04fdaae76 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java @@ -2523,21 +2523,33 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { result.setValue(duple.toString()); ITokenDuple[] segments = duple.getSegments(); int startingValue = 0; - if (segments.length > 0 && segments[0] instanceof IToken - && ((IToken) segments[0]).getType() == IToken.tCOLONCOLON) { - ++startingValue; - result.setFullyQualified(true); + if (segments.length > 0) { + final ITokenDuple firstSeg= segments[0]; + final IToken firstToken= firstSeg.getFirstToken(); + if (firstToken.getType() == IToken.tCOLONCOLON) { + if (firstToken == firstSeg.getLastToken() && firstSeg.getTemplateIdArgLists() == null) { + ++startingValue; + result.setFullyQualified(true); + } + } } for (int i = startingValue; i < segments.length; ++i) { IASTName subName = null; // take each name and add it to the result - if (segments[i] instanceof IToken) { - subName = createName((IToken) segments[i]); - } else if (segments[i].getTemplateIdArgLists() == null) - subName = createName(segments[i]); - else + final ITokenDuple seg= segments[i]; + if (seg.getTemplateIdArgLists() == null) { + final IToken firstToken= seg.getFirstToken(); + if (firstToken == seg.getLastToken()) { + subName= createName(firstToken); + } + else { + subName = createName(seg); + } + } + else { // templateID subName = createTemplateID(segments[i]); + } if (i == segments.length - 1 && duple instanceof OperatorTokenDuple) { // make sure the last segment is an OperatorName/ConversionName 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 db8ec1022ac..586b7b9c8ef 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 @@ -16,6 +16,7 @@ import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; import org.eclipse.cdt.core.dom.ast.IASTComment; import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTFunctionStyleMacroParameter; +import org.eclipse.cdt.core.dom.ast.IASTMacroExpansion; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; @@ -37,6 +38,7 @@ import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IMacroBinding; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree.IASTInclusionNode; +import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; /** @@ -51,10 +53,18 @@ abstract class ASTPreprocessorNode extends ASTNode { setLength(endNumber-startNumber); } - protected String getSource(int offset, int length) { - final IASTTranslationUnit tu= getTranslationUnit(); - IASTNodeLocation[] loc=tu.getLocationInfo(offset, length); - return tu.getUnpreprocessedSignature(loc); + protected char[] getSource(int offset, int length) { + final IASTTranslationUnit ast= getTranslationUnit(); + if (ast != null) { + ILocationResolver lr= (ILocationResolver) ast.getAdapter(ILocationResolver.class); + if (lr != null) { + final IASTFileLocation loc= lr.getMappedFileLocation(offset, length); + if (loc != null) { + return lr.getUnpreprocessedSignature(loc); + } + } + } + return CharArrayUtils.EMPTY; } public IASTNodeLocation[] getNodeLocations() { @@ -99,6 +109,13 @@ abstract class ASTPreprocessorNode extends ASTNode { } return super.getRawSignature(); } + + /** + * Returns a subnode surrounding the given range or this. + */ + IASTNode findSurroundingNode(int sequenceNumber, int length) { + return this; + } } @@ -111,7 +128,7 @@ class ASTComment extends ASTPreprocessorNode implements IASTComment { } public char[] getComment() { - return getSource(getOffset(), getLength()).toCharArray(); + return getSource(getOffset(), getLength()); } public boolean isBlockComment() { @@ -138,7 +155,7 @@ abstract class ASTDirectiveWithCondition extends ASTPreprocessorNode { } public String getConditionString() { - return getSource(fConditionOffset, getOffset() + getLength() - fConditionOffset); + return new String(getSource(fConditionOffset, getOffset() + getLength() - fConditionOffset)); } public char[] getCondition() { @@ -208,7 +225,7 @@ class ASTPragma extends ASTDirectiveWithCondition implements IASTPreprocessorPra } class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreprocessorIncludeStatement { - private final IASTName fName; + private final ASTPreprocessorName fName; private final String fPath; private final boolean fIsActive; private final boolean fIsResolved; @@ -243,6 +260,15 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces public boolean isSystemInclude() { return fIsSystemInclude; } + + IASTNode findSurroundingNode(int sequenceNumber, int length) { + final int nameSequencNumber= fName.getOffset(); + final int nameEndSequencNumber= nameSequencNumber + fName.getLength(); + if (nameSequencNumber <= sequenceNumber && sequenceNumber+length <= nameEndSequencNumber) { + return fName; + } + return this; + } } class ASTMacro extends ASTPreprocessorNode implements IASTPreprocessorObjectStyleMacroDefinition { @@ -282,6 +308,15 @@ class ASTMacro extends ASTPreprocessorNode implements IASTPreprocessorObjectStyl return (fName == n) ? r_definition : r_unclear; } + IASTNode findSurroundingNode(int sequenceNumber, int length) { + final int nameSequencNumber= fName.getOffset(); + final int nameEndSequencNumber= nameSequencNumber + fName.getLength(); + if (nameSequencNumber <= sequenceNumber && sequenceNumber+length <= nameEndSequencNumber) { + return fName; + } + return this; + } + public void setExpansion(String exp) {assert false;} public void setName(IASTName name) {assert false;} } @@ -333,7 +368,7 @@ class ASTFunctionMacro extends ASTMacro implements IASTPreprocessorFunctionStyle class ASTUndef extends ASTPreprocessorNode implements IASTPreprocessorUndefStatement { - private final IASTName fName; + private final ASTPreprocessorName fName; public ASTUndef(IASTTranslationUnit parent, char[] name, int startNumber, int nameNumber, int nameEndNumber, IBinding binding) { super(parent, IASTTranslationUnit.PREPROCESSOR_STATEMENT, startNumber, nameEndNumber); fName= new ASTPreprocessorName(this, IASTPreprocessorUndefStatement.MACRO_NAME, nameNumber, nameEndNumber, name, binding); @@ -342,6 +377,15 @@ class ASTUndef extends ASTPreprocessorNode implements IASTPreprocessorUndefState public IASTName getMacroName() { return fName; } + + IASTNode findSurroundingNode(int sequenceNumber, int length) { + final int nameSequencNumber= fName.getOffset(); + final int nameEndSequencNumber= nameSequencNumber + fName.getLength(); + if (nameSequencNumber <= sequenceNumber && sequenceNumber+length <= nameEndSequencNumber) { + return fName; + } + return this; + } } class ASTInclusionNode implements IASTInclusionNode { @@ -381,11 +425,11 @@ class DependencyTree extends ASTInclusionNode implements IDependencyTree { } class ASTFileLocation implements IASTFileLocation { - private FileLocationCtx fLocationCtx; + private LocationCtxFile fLocationCtx; private int fOffset; private int fLength; - public ASTFileLocation(FileLocationCtx fileLocationCtx, int startOffset, int length) { + public ASTFileLocation(LocationCtxFile fileLocationCtx, int startOffset, int length) { fLocationCtx= fileLocationCtx; fOffset= startOffset; fLength= length; @@ -419,6 +463,48 @@ class ASTFileLocation implements IASTFileLocation { public char[] getSource() { return fLocationCtx.getSource(fOffset, fLength); } + + public String toString() { + return getFileName() + "[" + fOffset + "," + (fOffset+fLength) + ")"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ + } +} + +class ASTMacroExpansionLocation implements IASTMacroExpansion { + + private LocationCtxMacroExpansion fContext; + private int fOffset; + private int fLength; + + public ASTMacroExpansionLocation(LocationCtxMacroExpansion macroExpansionCtx, int offset, int length) { + fContext= macroExpansionCtx; + fOffset= offset; + fLength= length; + } + + public IASTNodeLocation[] getExpansionLocations() { + final IASTFileLocation fl= asFileLocation(); + return fl == null ? new IASTNodeLocation[0] : new IASTNodeLocation[] {fl}; + } + + public IASTPreprocessorMacroDefinition getMacroDefinition() { + return fContext.getMacroDefinition(); + } + + public IASTFileLocation asFileLocation() { + return ((LocationCtxContainer) fContext.getParent()).createFileLocation(fContext.fOffsetInParent, fContext.fEndOffsetInParent-fContext.fOffsetInParent); + } + + public int getNodeLength() { + return fLength; + } + + public int getNodeOffset() { + return fOffset; + } + + public String toString() { + return fContext.getMacroDefinition().getName().toString() + "[" + fOffset + "," + (fOffset+fLength) + ")"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ + } } class ASTFileLocationForBuiltins implements IASTFileLocation { 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 abcb5392832..05ba2c6b9de 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 @@ -40,6 +40,7 @@ import org.eclipse.cdt.core.parser.ParserLanguage; import org.eclipse.cdt.core.parser.ast.IASTFactory; import org.eclipse.cdt.core.parser.util.CharArrayIntMap; import org.eclipse.cdt.core.parser.util.CharArrayObjectMap; +import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator.EvalException; import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions; import org.eclipse.cdt.internal.core.parser.scanner.MacroDefinitionParser.InvalidMacroDefinitionException; @@ -51,14 +52,6 @@ import org.eclipse.cdt.internal.core.parser.scanner2.ScannerUtility; * you should be using the {@link IScanner} interface. * @since 5.0 */ -/** - * @since 5.0 - * - */ -/** - * @since 5.0 - * - */ public class CPreprocessor implements ILexerLog, IScanner { public static final String PROP_VALUE = "CPreprocessor"; //$NON-NLS-1$ @@ -118,7 +111,7 @@ public class CPreprocessor implements ILexerLog, IScanner { StringBuffer buffer = new StringBuffer("\""); //$NON-NLS-1$ buffer.append(getCurrentFilename()); buffer.append('\"'); - return new ImageToken(IToken.tSTRING, null, 0, 0, buffer.toString().toCharArray()); + return new TokenWithImage(IToken.tSTRING, null, 0, 0, buffer.toString().toCharArray()); } }; final private DynamicStyleMacro __DATE__= new DynamicStyleMacro("__DATE__".toCharArray()) { //$NON-NLS-1$ @@ -137,7 +130,7 @@ public class CPreprocessor implements ILexerLog, IScanner { buffer.append(" "); //$NON-NLS-1$ buffer.append(cal.get(Calendar.YEAR)); buffer.append("\""); //$NON-NLS-1$ - return new ImageToken(IToken.tSTRING, null, 0, 0, buffer.toString().toCharArray()); + return new TokenWithImage(IToken.tSTRING, null, 0, 0, buffer.toString().toCharArray()); } }; @@ -157,14 +150,14 @@ public class CPreprocessor implements ILexerLog, IScanner { buffer.append(":"); //$NON-NLS-1$ append(buffer, cal.get(Calendar.SECOND)); buffer.append("\""); //$NON-NLS-1$ - return new ImageToken(IToken.tSTRING, null, 0, 0, buffer.toString().toCharArray()); + return new TokenWithImage(IToken.tSTRING, null, 0, 0, buffer.toString().toCharArray()); } }; final private DynamicStyleMacro __LINE__ = new DynamicStyleMacro("__LINE__".toCharArray()) { //$NON-NLS-1$ public Token execute() { int lineNumber= fLocationMap.getCurrentLineNumber(fCurrentContext.currentLexerToken().getOffset()); - return new ImageToken(IToken.tINTEGER, null, 0, 0, Long.toString(lineNumber).toCharArray()); + return new TokenWithImage(IToken.tINTEGER, null, 0, 0, Long.toString(lineNumber).toCharArray()); } }; @@ -240,6 +233,7 @@ public class CPreprocessor implements ILexerLog, IScanner { } public void setContentAssistMode(int offset) { + fContentAssistLimit= offset; fRootLexer.setContentAssistMode(offset); } @@ -441,8 +435,17 @@ public class CPreprocessor implements ILexerLog, IScanner { if (fContentAssistLimit < 0) { throw new EndOfFileException(); } - t1= new SimpleToken(IToken.tEOC, null, fContentAssistLimit, fContentAssistLimit); + int useType= IToken.tCOMPLETION; + if (fLastToken != null) { + final int lt= fLastToken.getType(); + if (lt == IToken.tCOMPLETION || lt == IToken.tEOC) { + useType= IToken.tEOC; + } + } + int sequenceNumber= fLocationMap.getSequenceNumberForOffset(fContentAssistLimit); + t1= new Token(useType, null, sequenceNumber, sequenceNumber); break; + case IToken.tSTRING: case IToken.tLSTRING: boolean isWide= tt1 == IToken.tLSTRING; @@ -480,7 +483,7 @@ public class CPreprocessor implements ILexerLog, IScanner { image[++off]= '"'; buf.getChars(0, buf.length(), image, ++off); image[image.length-1]= '"'; - t1= new ImageToken((isWide ? IToken.tLSTRING : IToken.tSTRING), null, t1.getOffset(), endOffset, image); + t1= new TokenWithImage((isWide ? IToken.tLSTRING : IToken.tSTRING), null, t1.getOffset(), endOffset, image); } } @@ -653,7 +656,7 @@ public class CPreprocessor implements ILexerLog, IScanner { if (isHex && !hasExponent) { continue; } - if (isFloat && !isHex && !hasExponent && pos+1 >= image.length) { + if (isFloat && !isHex && !hasExponent && pos+1 <= image.length) { switch (image[pos+1]) { case '+': case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': @@ -841,14 +844,13 @@ public class CPreprocessor implements ILexerLog, IScanner { // we have an identifier final char[] name = ident.getCharImage(); final int type = fPPKeywords.get(name); - int endOffset; + int condEndOffset; switch (type) { case IPreprocessorDirective.ppImport: case IPreprocessorDirective.ppInclude: if (fExpandingMacro) { - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - endOffset= lexer.currentToken().getEndOffset(); - handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, name, startOffset, endOffset); + condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, name, startOffset, condEndOffset); } else { executeInclude(lexer, startOffset, false, true); @@ -879,35 +881,33 @@ public class CPreprocessor implements ILexerLog, IScanner { break; case IPreprocessorDirective.ppElse: lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - endOffset= lexer.currentToken().getEndOffset(); if (fCurrentContext.changeBranch(ScannerContext.BRANCH_ELSE)) { - fLocationMap.encounterPoundElse(startOffset, endOffset, false); + fLocationMap.encounterPoundElse(startOffset, ident.getEndOffset(), false); skipOverConditionalCode(lexer, false); } else { - handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, startOffset, endOffset); + handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, startOffset, ident.getEndOffset()); } break; case IPreprocessorDirective.ppElif: int condOffset= lexer.nextToken().getOffset(); - int condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - endOffset= lexer.currentToken().getEndOffset(); + condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + int endOffset= lexer.currentToken().getEndOffset(); if (fCurrentContext.changeBranch(ScannerContext.BRANCH_ELIF)) { fLocationMap.encounterPoundElif(startOffset, condOffset, condEndOffset, endOffset, false); skipOverConditionalCode(lexer, false); } else { - handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, startOffset, endOffset); + handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, startOffset, condEndOffset); } break; case IPreprocessorDirective.ppEndif: - condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - endOffset= lexer.currentToken().getEndOffset(); + lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); if (fCurrentContext.changeBranch(ScannerContext.BRANCH_END)) { - fLocationMap.encounterPoundEndIf(startOffset, condEndOffset); + fLocationMap.encounterPoundEndIf(startOffset, ident.getEndOffset()); } else { - handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, startOffset, endOffset); + handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, startOffset, ident.getEndOffset()); } break; case IPreprocessorDirective.ppWarning: @@ -932,9 +932,9 @@ public class CPreprocessor implements ILexerLog, IScanner { lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); break; default: - lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); + condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); endOffset= lexer.currentToken().getEndOffset(); - handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, name, startOffset, endOffset); + handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, name, startOffset, condEndOffset); break; } } @@ -962,8 +962,13 @@ public class CPreprocessor implements ILexerLog, IScanner { case Lexer.tQUOTE_HEADER_NAME: image= header.getCharImage(); - headerName= new char[image.length-2]; - System.arraycopy(image, 1, headerName, 0, headerName.length); + if (image.length <= 2) { + headerName= CharArrayUtils.EMPTY; + } + else { + headerName= new char[image.length-2]; + System.arraycopy(image, 1, headerName, 0, headerName.length); + } lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); endOffset= lexer.currentToken().getEndOffset(); break; @@ -1011,7 +1016,7 @@ public class CPreprocessor implements ILexerLog, IScanner { if (headerName == null || headerName.length==0) { if (active) { handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, - lexer.getInputChars(poundOffset, endOffset), poundOffset, endOffset); + lexer.getInputChars(poundOffset, endOffset), poundOffset, nameEndOffset); } return; } @@ -1032,7 +1037,7 @@ public class CPreprocessor implements ILexerLog, IScanner { } } else { - handleProblem(IProblem.PREPROCESSOR_INCLUSION_NOT_FOUND, headerName, poundOffset, endOffset); + handleProblem(IProblem.PREPROCESSOR_INCLUSION_NOT_FOUND, headerName, poundOffset, nameEndOffset); } } else { @@ -1240,16 +1245,15 @@ public class CPreprocessor implements ILexerLog, IScanner { break; case IPreprocessorDirective.ppElse: lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - endOffset= lexer.currentToken().getEndOffset(); if (fCurrentContext.changeBranch(ScannerContext.BRANCH_ELSE)) { boolean isActive= nesting == 0 && takeElseBranch; - fLocationMap.encounterPoundElse(pound.getOffset(), endOffset, isActive); + fLocationMap.encounterPoundElse(pound.getOffset(), ident.getEndOffset(), isActive); if (isActive) { return; } } else { - handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, pound.getOffset(), endOffset); + handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, pound.getOffset(), ident.getEndOffset()); } break; case IPreprocessorDirective.ppElif: @@ -1286,16 +1290,15 @@ public class CPreprocessor implements ILexerLog, IScanner { break; case IPreprocessorDirective.ppEndif: lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE); - endOffset= lexer.currentToken().getEndOffset(); if (fCurrentContext.changeBranch(ScannerContext.BRANCH_END)) { - fLocationMap.encounterPoundEndIf(pound.getOffset(), endOffset); + fLocationMap.encounterPoundEndIf(pound.getOffset(), ident.getEndOffset()); if (nesting == 0) { return; } --nesting; } else { - handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, pound.getOffset(), endOffset); + handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, pound.getOffset(), ident.getEndOffset()); } break; default: diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ExpressionEvaluator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ExpressionEvaluator.java index 0a942bef314..f80f52f5fe7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ExpressionEvaluator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ExpressionEvaluator.java @@ -272,7 +272,7 @@ class ExpressionEvaluator { private void consume() { fTokens= (Token) fTokens.getNext(); if (fTokens == null) { - fTokens= new SimpleToken(Lexer.tEND_OF_INPUT, null, 0, 0); + fTokens= new Token(Lexer.tEND_OF_INPUT, null, 0, 0); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationResolver.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationResolver.java index d9ab68aca86..a3d7295bce6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationResolver.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationResolver.java @@ -12,7 +12,10 @@ package org.eclipse.cdt.internal.core.parser.scanner; import org.eclipse.cdt.core.dom.ast.IASTComment; +import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement; @@ -60,33 +63,66 @@ public interface ILocationResolver extends org.eclipse.cdt.internal.core.parser. IASTProblem[] getScannerProblems(); /** + * Returns the comments encountered. + */ + IASTComment[] getComments(); + + /** * @see IASTTranslationUnit#getFilePath() */ - public String getTranslationUnitPath(); + String getTranslationUnitPath(); /** * @see IASTTranslationUnit#getContainingFilename() * mstodo- scanner removal should be renamed */ - public String getContainingFilename(int offset); + String getContainingFilename(int sequenceNumber); /** * @see IASTTranslationUnit#getDependencyTree() */ - public IDependencyTree getDependencyTree(); + IDependencyTree getDependencyTree(); /** * Returns explicit and implicit references for a macro. */ - public IASTName[] getReferences(IMacroBinding binding); + IASTName[] getReferences(IMacroBinding binding); /** * Returns the definition for a macro. */ - public IASTName[] getDeclarations(IMacroBinding binding); + IASTName[] getDeclarations(IMacroBinding binding); + + /** + * Returns the smallest file location, that encloses the given global range. In case the range + * spans over multiple files, the files are mapped to include statements until all of them are + * found in the same file. So the resulting location contains the include directives that actually + * cause the range to be part of the AST. + * @param offset sequence number as stored in the ASTNodes. + * @param length + */ + IASTFileLocation getMappedFileLocation(int offset, int length); /** - * Returns the comments encountered. + * @see IASTTranslationUnit#getLocationInfo(int, int). */ - IASTComment[] getComments(); + IASTNodeLocation[] getLocations(int sequenceNumber, int length); + + /** + * Returns the sequence-number for the given file-path and offset, or -1 if this file + * is not part of the translation-unit. + * @param filePath a file path or null to specify the root of the translation unit. + * @param fileOffset an offset into the source of the file. + */ + int getSequenceNumberForFileOffset(String filePath, int fileOffset); + + /** + * @see IASTTranslationUnit#getUnpreprocessedSignature(IASTFileLocation). + */ + char[] getUnpreprocessedSignature(IASTFileLocation loc); + + /** + * Returns a preprocessor node surrounding the given range, or null. + */ + IASTNode findSurroundingPreprocessorNode(int sequenceNumber, int length); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Lexer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Lexer.java index 758e55d04cd..49f005bd3d8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Lexer.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Lexer.java @@ -96,7 +96,7 @@ final public class Lexer { fOptions= options; fLog= log; fSource= source; - fToken= new SimpleToken(tBEFORE_INPUT, source, start, start); + fToken= new Token(tBEFORE_INPUT, source, start, start); nextCharPhase3(); } @@ -601,20 +601,25 @@ final public class Lexer { } private Token newToken(int kind, int offset) { - return new SimpleToken(kind, fSource, offset, fOffset); + return new Token(kind, fSource, offset, fOffset); } private Token newDigraphToken(int kind, int offset) { - return new DigraphToken(kind, fSource, offset, fOffset); + return new TokenForDigraph(kind, fSource, offset, fOffset); } - private Token newToken(int kind, int offset, int imageLength) { + private Token newToken(final int kind, final int offset, final int imageLength) { final int endOffset= fOffset; - int sourceLen= endOffset-offset; + final int sourceLen= endOffset-offset; + char[] image; if (sourceLen != imageLength) { - return new ImageToken(kind, fSource, offset, endOffset, getCharImage(offset, endOffset, imageLength)); + image= getCharImage(offset, endOffset, imageLength); } - return new SourceImageToken(kind, fSource, offset, endOffset, fInput); + else { + image= new char[imageLength]; + System.arraycopy(fInput, offset, image, 0, imageLength); + } + return new TokenWithImage(kind, fSource, offset, endOffset, image); } private void handleProblem(int problemID, char[] arg, int offset) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtx.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtx.java index 504501c6277..133210f432b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtx.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtx.java @@ -11,8 +11,8 @@ package org.eclipse.cdt.internal.core.parser.scanner; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; +import java.util.Collection; +import java.util.Collections; import org.eclipse.cdt.core.dom.ast.IASTFileLocation; @@ -22,15 +22,24 @@ import org.eclipse.cdt.core.dom.ast.IASTFileLocation; * @since 5.0 */ abstract class LocationCtx implements ILocationCtx { - final ContainerLocationCtx fParent; + final LocationCtxContainer fParent; + /** + * The first sequence number used by this context. + */ final int fSequenceNumber; - final int fParentOffset; - final int fParentEndOffset; + /** + * The offset of the denotation of this context in the parent's source. This is no sequence number. + */ + final int fOffsetInParent; + /** + * The end-offset of the denotation of this context in the parent's source. This is no sequence number. + */ + final int fEndOffsetInParent; - public LocationCtx(ContainerLocationCtx parent, int parentOffset, int parentEndOffset, int sequenceNumber) { + public LocationCtx(LocationCtxContainer parent, int parentOffset, int parentEndOffset, int sequenceNumber) { fParent= parent; - fParentOffset= parentOffset; - fParentEndOffset= parentEndOffset; + fOffsetInParent= parentOffset; + fEndOffsetInParent= parentEndOffset; fSequenceNumber= sequenceNumber; if (parent != null) { parent.addChild(this); @@ -77,7 +86,7 @@ abstract class LocationCtx implements ILocationCtx { * Returns the minimal context containing the specified range, assuming that it is contained in * this context. */ - public LocationCtx ctxForNumberRange(int sequenceNumber, int length) { + public LocationCtx findSurroundingContext(int sequenceNumber, int length) { return this; } @@ -85,17 +94,23 @@ abstract class LocationCtx implements ILocationCtx { * Returns the minimal file location containing the specified sequence number range, assuming * that it is contained in this context. */ - public IASTFileLocation fileLocationForNumberRange(int sequenceNumber, int length) { - return fParent.fileLocationForOffsetRange(fParentOffset, fParentEndOffset-fParentOffset); + public IASTFileLocation findMappedFileLocation(int sequenceNumber, int length) { + return fParent.createMappedFileLocation(fOffsetInParent, fEndOffsetInParent-fOffsetInParent); } /** * Returns the file location containing the specified offset range in this context. */ - public IASTFileLocation fileLocationForOffsetRange(int parentOffset, int length) { - return fParent.fileLocationForOffsetRange(fParentOffset, fParentEndOffset-fParentOffset); + public IASTFileLocation createMappedFileLocation(int offset, int length) { + return fParent.createMappedFileLocation(fOffsetInParent, fEndOffsetInParent-fOffsetInParent); } + /** + * Returns the sequence of file locations spanning the given range. + * Assumes that the range starts within this context. + */ + public abstract boolean collectLocations(int sequenceNumber, int length, ArrayList sofar); + /** * Support for the dependency tree, add inclusion statements found in this context. */ @@ -108,228 +123,8 @@ abstract class LocationCtx implements ILocationCtx { public ASTInclusionStatement getInclusionStatement() { return null; } -} -class ContainerLocationCtx extends LocationCtx { - private int fChildSequenceLength; - private ArrayList fChildren; - private char[] fSource; - private int[] fLineOffsets; - - public ContainerLocationCtx(ContainerLocationCtx parent, char[] source, int parentOffset, int parentEndOffset, int sequenceNumber) { - super(parent, parentOffset, parentEndOffset, sequenceNumber); - fSource= source; - } - - public void addChild(LocationCtx locationCtx) { - if (fChildren == null) { - fChildren= new ArrayList(); - } - fChildren.add(locationCtx); - } - - public char[] getSource(int offset, int length) { - offset= Math.max(0, Math.min(offset, fSource.length)); - length= Math.max(0, Math.min(length, fSource.length-offset)); - char[] result= new char[length]; - System.arraycopy(fSource, offset, result, 0, length); - return result; - } - - public final int getSequenceLength() { - return fSource.length + fChildSequenceLength; - } - public final int getSequenceNumberForOffset(int offset, boolean checkChildren) { - int result= fSequenceNumber + fChildSequenceLength + offset; - if (checkChildren && fChildren != null) { - for (int i= fChildren.size()-1; i >= 0; i--) { - final LocationCtx child= (LocationCtx) fChildren.get(i); - if (child.fParentEndOffset > offset) { // child was inserted behind the offset, adjust sequence number - result-= child.getSequenceLength(); - } - else { - return result; - } - } - } - return result; - } - - public void addChildSequenceLength(int childLength) { - fChildSequenceLength+= childLength; - } - - public final LocationCtx ctxForNumberRange(int sequenceNumber, int length) { - int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber; - final LocationCtx child= findChildLessOrEqualThan(sequenceNumber); - if (child != null && child.fSequenceNumber+child.getSequenceLength() > testEnd) { - return child.ctxForNumberRange(sequenceNumber, length); - } - return this; - } - - public IASTFileLocation fileLocationForNumberRange(int sequenceNumber, int length) { - // try to delegate to a child. - int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber; - final LocationCtx child= findChildLessOrEqualThan(sequenceNumber); - if (child != null && child.fSequenceNumber+child.getSequenceLength() > testEnd) { - if (testEnd == sequenceNumber || findChildLessOrEqualThan(testEnd) == child) { - return child.fileLocationForNumberRange(sequenceNumber, length); - } - } - return super.fileLocationForNumberRange(sequenceNumber, length); - } - - final LocationCtx findChildLessOrEqualThan(final int sequenceNumber) { - if (fChildren == null) { - return null; - } - int upper= fChildren.size(); - int lower= 0; - while (upper > lower) { - int middle= (upper+lower)/2; - LocationCtx child= (LocationCtx) fChildren.get(middle); - if (child.fSequenceNumber <= sequenceNumber) { - lower= middle+1; - } - else { - upper= middle; - } - } - if (lower > 0) { - return (LocationCtx) fChildren.get(lower-1); - } - return null; - } - - public void getInclusions(ArrayList result) { - if (fChildren != null) { - for (Iterator iterator = fChildren.iterator(); iterator.hasNext();) { - LocationCtx ctx= (LocationCtx) iterator.next(); - if (ctx.getInclusionStatement() != null) { - result.add(new ASTInclusionNode(ctx)); - } - else { - ctx.getInclusions(result); - } - } - } - } - - - public int getLineNumber(int offset) { - if (fLineOffsets == null) { - fLineOffsets= computeLineOffsets(); - } - int idx= Arrays.binarySearch(fLineOffsets, offset); - if (idx < 0) { - return -idx; - } - return idx+1; - } - - private int[] computeLineOffsets() { - ArrayList offsets= new ArrayList(); - for (int i = 0; i < fSource.length; i++) { - if (fSource[i] == '\n') { - offsets.add(new Integer(i)); - } - } - int[] result= new int[offsets.size()]; - for (int i = 0; i < result.length; i++) { - result[i]= ((Integer) offsets.get(i)).intValue(); - - } - return result; - } - -} - -class FileLocationCtx extends ContainerLocationCtx { - private final String fFilename; - private final ASTInclusionStatement fASTInclude; - - public FileLocationCtx(ContainerLocationCtx parent, String filename, char[] source, int parentOffset, int parentEndOffset, int sequenceNumber, ASTInclusionStatement inclusionStatement) { - super(parent, source, parentOffset, parentEndOffset, sequenceNumber); - fFilename= new String(filename); - fASTInclude= inclusionStatement; - } - - public final void addChildSequenceLength(int childLength) { - super.addChildSequenceLength(childLength); - if (fASTInclude != null) { - fASTInclude.setLength(fASTInclude.getLength()+childLength); - } - } - - public final String getFilePath() { - return fFilename; - } - - public IASTFileLocation fileLocationForNumberRange(int sequenceNumber, int length) { - // try to delegate to a child. - final int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber; - final int sequenceEnd= sequenceNumber+length; - final LocationCtx child1= findChildLessOrEqualThan(sequenceNumber); - final LocationCtx child2= testEnd == sequenceNumber ? child1 : findChildLessOrEqualThan(testEnd); - - if (child1 == child2 && child1 != null && child1.fSequenceNumber + child1.getSequenceLength() > testEnd) { - return child1.fileLocationForNumberRange(sequenceNumber, length); - } - - // handle here - int startOffset; - int endOffset; - - if (child1 == null) { - startOffset= sequenceNumber-fSequenceNumber; - } - else { - int childSequenceEnd= child1.fSequenceNumber + child1.getSequenceLength(); - if (sequenceNumber < childSequenceEnd) { - startOffset= child1.fParentOffset; - } - else { // start beyond child1 - startOffset= child1.fParentEndOffset + sequenceNumber-childSequenceEnd; - } - } - if (child2 == null) { - endOffset= sequenceEnd-fSequenceNumber; - } - else { - int childSequenceEnd= child2.fSequenceNumber + child2.getSequenceLength(); - if (childSequenceEnd < sequenceEnd) { // beyond child2 - endOffset= child2.fParentEndOffset+sequenceEnd-childSequenceEnd; - } - else { - endOffset= child2.fParentEndOffset; - } - } - return new ASTFileLocation(this, startOffset, endOffset-startOffset); - } - - public IASTFileLocation fileLocationForOffsetRange(int offset, int length) { - return new ASTFileLocation(this, offset, length); - } - - public ASTInclusionStatement getInclusionStatement() { - return fASTInclude; + public Collection getChildren() { + return Collections.EMPTY_SET; } } - - -class MacroExpansionCtx extends LocationCtx { - private final int fLength; - - public MacroExpansionCtx(ContainerLocationCtx parent, int parentOffset, int parentEndOffset, - int sequenceNumber, int length, ImageLocationInfo[] imageLocations, ASTPreprocessorName expansion) { - super(parent, parentOffset, parentEndOffset, sequenceNumber); - fLength= length; - } - - public int getSequenceLength() { - return fLength; - } - - // mstodo- image locations -} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxContainer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxContainer.java new file mode 100644 index 00000000000..63f2dbfea63 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxContainer.java @@ -0,0 +1,220 @@ +/******************************************************************************* + * Copyright (c) 2007 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.parser.scanner; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; + +import org.eclipse.cdt.core.dom.ast.IASTFileLocation; + +/** + * Base class for all location contexts that can contain children. + *

+ * @since 5.0 + */ +class LocationCtxContainer extends LocationCtx { + /** + * The total length of all children in terms of sequence numbers. + */ + private int fChildSequenceLength; + + private ArrayList fChildren; + private char[] fSource; + private int[] fLineOffsets; + + public LocationCtxContainer(LocationCtxContainer parent, char[] source, int parentOffset, int parentEndOffset, int sequenceNumber) { + super(parent, parentOffset, parentEndOffset, sequenceNumber); + fSource= source; + } + + public Collection getChildren() { + return fChildren == null ? Collections.EMPTY_LIST : fChildren; + } + + public void addChild(LocationCtx locationCtx) { + if (fChildren == null) { + fChildren= new ArrayList(); + } + fChildren.add(locationCtx); + } + + public char[] getSource(int offset, int length) { + offset= Math.max(0, Math.min(offset, fSource.length)); + length= Math.max(0, Math.min(length, fSource.length-offset)); + char[] result= new char[length]; + System.arraycopy(fSource, offset, result, 0, length); + return result; + } + + public final int getSequenceLength() { + return fSource.length + fChildSequenceLength; + } + + public final int getSequenceNumberForOffset(int offset, boolean checkChildren) { + int result= fSequenceNumber + fChildSequenceLength + offset; + if (checkChildren && fChildren != null) { + for (int i= fChildren.size()-1; i >= 0; i--) { + final LocationCtx child= (LocationCtx) fChildren.get(i); + if (child.fEndOffsetInParent > offset) { // child was inserted behind the offset, adjust sequence number + result-= child.getSequenceLength(); + } + else { + return result; + } + } + } + return result; + } + + public void addChildSequenceLength(int childLength) { + fChildSequenceLength+= childLength; + } + + public final LocationCtx findSurroundingContext(int sequenceNumber, int length) { + int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber; + final LocationCtx child= findChildLessOrEqualThan(sequenceNumber); + if (child != null && child.fSequenceNumber+child.getSequenceLength() > testEnd) { + return child.findSurroundingContext(sequenceNumber, length); + } + return this; + } + + public IASTFileLocation findMappedFileLocation(int sequenceNumber, int length) { + // try to delegate to a child. + int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber; + final LocationCtx child= findChildLessOrEqualThan(sequenceNumber); + if (child != null && child.fSequenceNumber+child.getSequenceLength() > testEnd) { + return child.findMappedFileLocation(sequenceNumber, length); + } + return super.findMappedFileLocation(sequenceNumber, length); + } + + public boolean collectLocations(int sequenceNumber, final int length, ArrayList locations) { + final int endSequenceNumber= sequenceNumber+length; + if (fChildren != null) { + int childIdx= Math.max(0, findChildIdxLessOrEqualThan(sequenceNumber)); + for (; childIdx < fChildren.size(); childIdx++) { + final LocationCtx child= (LocationCtx) fChildren.get(childIdx); + + // create the location between start and the child + if (sequenceNumber < child.fSequenceNumber) { + // compute offset backwards from the child's offset + final int offset= child.fEndOffsetInParent - (child.fSequenceNumber - sequenceNumber); + // it the child is not affected, we are done. + if (endSequenceNumber <= child.fSequenceNumber) { + addFileLocation(offset, endSequenceNumber-sequenceNumber, locations); + return true; + } + addFileLocation(offset, child.fOffsetInParent-offset, locations); + sequenceNumber= child.fSequenceNumber; + } + + // let the child create locations + final int childEndSequenceNumber= child.fSequenceNumber + child.getSequenceLength(); + if (sequenceNumber < childEndSequenceNumber) { + if (child.collectLocations(sequenceNumber, endSequenceNumber-sequenceNumber, locations)) { + return true; + } + sequenceNumber= childEndSequenceNumber; + } + } + } + + // create the location after the last child. + final int myEndNumber = fSequenceNumber + getSequenceLength(); + final int offset= fSource.length - (myEndNumber - sequenceNumber); + if (endSequenceNumber <= myEndNumber) { + addFileLocation(offset, endSequenceNumber-sequenceNumber, locations); + return true; + } + addFileLocation(offset, fSource.length-offset, locations); + return false; + } + + private ArrayList addFileLocation(int offset, int length, ArrayList sofar) { + IASTFileLocation loc= createFileLocation(offset, length); + if (loc != null) { + sofar.add(loc); + } + return sofar; + } + + ASTFileLocation createFileLocation(int start, int length) { + return null; + } + + final int findChildIdxLessOrEqualThan(int sequenceNumber) { + if (fChildren == null) { + return -1; + } + int upper= fChildren.size(); + int lower= 0; + while (upper > lower) { + int middle= (upper+lower)/2; + LocationCtx child= (LocationCtx) fChildren.get(middle); + if (child.fSequenceNumber <= sequenceNumber) { + lower= middle+1; + } + else { + upper= middle; + } + } + return lower-1; + } + + final LocationCtx findChildLessOrEqualThan(final int sequenceNumber) { + final int idx= findChildIdxLessOrEqualThan(sequenceNumber); + return idx >= 0 ? (LocationCtx) fChildren.get(idx) : null; + } + + public void getInclusions(ArrayList result) { + if (fChildren != null) { + for (Iterator iterator = fChildren.iterator(); iterator.hasNext();) { + LocationCtx ctx= (LocationCtx) iterator.next(); + if (ctx.getInclusionStatement() != null) { + result.add(new ASTInclusionNode(ctx)); + } + else { + ctx.getInclusions(result); + } + } + } + } + + public int getLineNumber(int offset) { + if (fLineOffsets == null) { + fLineOffsets= computeLineOffsets(); + } + int idx= Arrays.binarySearch(fLineOffsets, offset); + if (idx < 0) { + return -idx; + } + return idx+1; + } + + private int[] computeLineOffsets() { + ArrayList offsets= new ArrayList(); + for (int i = 0; i < fSource.length; i++) { + if (fSource[i] == '\n') { + offsets.add(new Integer(i)); + } + } + int[] result= new int[offsets.size()]; + for (int i = 0; i < result.length; i++) { + result[i]= ((Integer) offsets.get(i)).intValue(); + + } + return result; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxFile.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxFile.java new file mode 100644 index 00000000000..ebc0875a89a --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxFile.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2007 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.parser.scanner; + +import org.eclipse.cdt.core.dom.ast.IASTFileLocation; + +/** + * A location context representing a file. + * @since 5.0 + */ +class LocationCtxFile extends LocationCtxContainer { + private final String fFilename; + private final ASTInclusionStatement fASTInclude; + + public LocationCtxFile(LocationCtxContainer parent, String filename, char[] source, int parentOffset, int parentEndOffset, int sequenceNumber, ASTInclusionStatement inclusionStatement) { + super(parent, source, parentOffset, parentEndOffset, sequenceNumber); + fFilename= new String(filename); + fASTInclude= inclusionStatement; + } + + public final void addChildSequenceLength(int childLength) { + super.addChildSequenceLength(childLength); + if (fASTInclude != null) { + fASTInclude.setLength(fASTInclude.getLength()+childLength); + } + } + + public final String getFilePath() { + return fFilename; + } + + public IASTFileLocation findMappedFileLocation(int sequenceNumber, int length) { + // try to delegate to a child. + final int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber; + final int sequenceEnd= sequenceNumber+length; + final LocationCtx child1= findChildLessOrEqualThan(sequenceNumber); + final LocationCtx child2= testEnd == sequenceNumber ? child1 : findChildLessOrEqualThan(testEnd); + + if (child1 == child2 && child1 != null && child1.fSequenceNumber + child1.getSequenceLength() > testEnd) { + return child1.findMappedFileLocation(sequenceNumber, length); + } + + // handle here + int startOffset; + int endOffset; + + if (child1 == null) { + startOffset= sequenceNumber-fSequenceNumber; + } + else { + int childSequenceEnd= child1.fSequenceNumber + child1.getSequenceLength(); + if (sequenceNumber < childSequenceEnd) { + startOffset= child1.fOffsetInParent; + } + else { // start beyond child1 + startOffset= child1.fEndOffsetInParent + sequenceNumber-childSequenceEnd; + } + } + if (child2 == null) { + endOffset= sequenceEnd-fSequenceNumber; + } + else { + int childSequenceEnd= child2.fSequenceNumber + child2.getSequenceLength(); + if (childSequenceEnd < sequenceEnd) { // beyond child2 + endOffset= child2.fEndOffsetInParent+sequenceEnd-childSequenceEnd; + } + else { + endOffset= child2.fEndOffsetInParent; + } + } + return new ASTFileLocation(this, startOffset, endOffset-startOffset); + } + + public IASTFileLocation createMappedFileLocation(int offset, int length) { + return new ASTFileLocation(this, offset, length); + } + + public ASTInclusionStatement getInclusionStatement() { + return fASTInclude; + } + + ASTFileLocation createFileLocation(int start, int length) { + return new ASTFileLocation(this, start, length); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxMacroExpansion.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxMacroExpansion.java new file mode 100644 index 00000000000..1baac253295 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxMacroExpansion.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2007 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.parser.scanner; + +import java.util.ArrayList; + +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition; +import org.eclipse.cdt.core.dom.ast.IMacroBinding; + +/** + * A location context representing macro expansions. + * @since 5.0 + */ +class LocationCtxMacroExpansion extends LocationCtx { + private final LocationMap fLocationMap; + private final int fLength; + private ASTMacroReferenceName fName; + + public LocationCtxMacroExpansion(LocationMap map, LocationCtxContainer parent, int parentOffset, int parentEndOffset, + int sequenceNumber, int length, ImageLocationInfo[] imageLocations, ASTMacroReferenceName expansion) { + super(parent, parentOffset, parentEndOffset, sequenceNumber); + fLocationMap= map; + fLength= length; + fName= expansion; + } + + public int getSequenceLength() { + return fLength; + } + + public boolean collectLocations(int start, int length, ArrayList locations) { + final int offset= start-fSequenceNumber; + assert offset >= 0 && length >= 0; + + if (offset+length <= fLength) { + locations.add(new ASTMacroExpansionLocation(this, offset, length)); + return true; + } + + locations.add(new ASTMacroExpansionLocation(this, offset, fLength-offset)); + return false; + } + + public IASTPreprocessorMacroDefinition getMacroDefinition() { + return fLocationMap.getMacroDefinition((IMacroBinding) fName.getBinding()); + } +} + + 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 7891c7c92b3..17cf3387674 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 @@ -13,11 +13,13 @@ package org.eclipse.cdt.internal.core.parser.scanner; import java.util.ArrayList; import java.util.IdentityHashMap; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import org.eclipse.cdt.core.dom.ast.IASTComment; import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition; @@ -44,7 +46,7 @@ public class LocationMap implements ILocationResolver { private ArrayList fProblems= new ArrayList(); private ArrayList fComments= new ArrayList(); private ArrayList fBuiltinMacros= new ArrayList(); - private IdentityHashMap fMacroExpansions= new IdentityHashMap(); + private IdentityHashMap fMacroReferences= new IdentityHashMap(); private LocationCtx fRootContext= null; private LocationCtx fCurrentContext= null; @@ -81,7 +83,7 @@ public class LocationMap implements ILocationResolver { public ILocationCtx pushTranslationUnit(String filename, char[] buffer) { assert fCurrentContext == null; fTranslationUnitPath= filename; - fRootContext= fCurrentContext= new FileLocationCtx(null, filename, buffer, 0, 0, 0, null); + fRootContext= fCurrentContext= new LocationCtxFile(null, filename, buffer, 0, 0, 0, null); fLastChildInsertionOffset= 0; return fCurrentContext; } @@ -93,9 +95,9 @@ public class LocationMap implements ILocationResolver { * @param isMacroFile whether the context is used for running the preprocessor, only. */ public ILocationCtx pushPreInclusion(char[] buffer, int offset, boolean isMacroFile) { - assert fCurrentContext instanceof ContainerLocationCtx; + assert fCurrentContext instanceof LocationCtxContainer; int sequenceNumber= getSequenceNumberForOffset(offset); - fCurrentContext= new ContainerLocationCtx((ContainerLocationCtx) fCurrentContext, buffer, offset, offset, sequenceNumber); + fCurrentContext= new LocationCtxContainer((LocationCtxContainer) fCurrentContext, buffer, offset, offset, sequenceNumber); fLastChildInsertionOffset= 0; return fCurrentContext; } @@ -112,7 +114,7 @@ public class LocationMap implements ILocationResolver { */ public ILocationCtx pushInclusion(int startOffset, int nameOffset, int nameEndOffset, int endOffset, char[] buffer, String filename, char[] name, boolean userInclude) { - assert fCurrentContext instanceof ContainerLocationCtx; + assert fCurrentContext instanceof LocationCtxContainer; int startNumber= getSequenceNumberForOffset(startOffset); int nameNumber= getSequenceNumberForOffset(nameOffset); int nameEndNumber= getSequenceNumberForOffset(nameEndOffset); @@ -120,7 +122,7 @@ public class LocationMap implements ILocationResolver { final ASTInclusionStatement inclusionStatement= new ASTInclusionStatement(fTranslationUnit, startNumber, nameNumber, nameEndNumber, name, filename, userInclude, true); fDirectives.add(inclusionStatement); - fCurrentContext= new FileLocationCtx((ContainerLocationCtx) fCurrentContext, filename, buffer, startOffset, endOffset, endNumber, inclusionStatement); + fCurrentContext= new LocationCtxFile((LocationCtxContainer) fCurrentContext, filename, buffer, startOffset, endOffset, endNumber, inclusionStatement); fLastChildInsertionOffset= 0; return fCurrentContext; } @@ -146,7 +148,7 @@ public class LocationMap implements ILocationResolver { */ public ILocationCtx pushMacroExpansion(int nameOffset, int nameEndOffset, int endOffset, int contextLength, IMacroBinding macro, IASTName[] implicitMacroReferences, ImageLocationInfo[] imageLocations) { - assert fCurrentContext instanceof ContainerLocationCtx; + assert fCurrentContext instanceof LocationCtxContainer; int nameNumber= getSequenceNumberForOffset(nameOffset); int nameEndNumber= getSequenceNumberForOffset(nameEndOffset); @@ -156,22 +158,22 @@ public class LocationMap implements ILocationResolver { for (int i = 0; i < implicitMacroReferences.length; i++) { ASTMacroReferenceName name = (ASTMacroReferenceName) implicitMacroReferences[i]; name.setOffsetAndLength(nameNumber, length); - addExpansion((IMacroBinding) name.getBinding(), name); + addMacroReference((IMacroBinding) name.getBinding(), name); } ASTMacroReferenceName expansion= new ASTMacroReferenceName(fTranslationUnit, nameNumber, nameEndNumber, macro, null); - addExpansion(macro, expansion); + addMacroReference(macro, expansion); - fCurrentContext= new MacroExpansionCtx((ContainerLocationCtx) fCurrentContext, nameOffset, endOffset, endNumber, contextLength, imageLocations, expansion); + fCurrentContext= new LocationCtxMacroExpansion(this, (LocationCtxContainer) fCurrentContext, nameOffset, endOffset, endNumber, contextLength, imageLocations, expansion); fLastChildInsertionOffset= 0; return fCurrentContext; } - private void addExpansion(IMacroBinding macro, ASTPreprocessorName name) { - List list= (List) fMacroExpansions.get(macro); + private void addMacroReference(IMacroBinding macro, IASTName name) { + List list= (List) fMacroReferences.get(macro); if (list == null) { list= new ArrayList(); - fMacroExpansions.put(macro, list); + fMacroReferences.put(macro, list); } list.add(name); } @@ -186,7 +188,7 @@ public class LocationMap implements ILocationResolver { final LocationCtx parent= (LocationCtx) fCurrentContext.getParent(); if (parent != null) { fCurrentContext= parent; - fLastChildInsertionOffset= child.fParentEndOffset; + fLastChildInsertionOffset= child.fEndOffsetInParent; parent.addChildSequenceLength(child.getSequenceLength()); } } @@ -206,7 +208,7 @@ public class LocationMap implements ILocationResolver { startOffset= getSequenceNumberForOffset(startOffset); nameOffset= getSequenceNumberForOffset(nameOffset); nameEndOffset= getSequenceNumberForOffset(nameEndOffset); -// endOffset= getSequenceNumberForOffset(endOffset); + // not using endOffset, compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset); fDirectives.add(new ASTInclusionStatement(fTranslationUnit, startOffset, nameOffset, nameEndOffset, name, filename, userInclude, active)); } @@ -247,7 +249,7 @@ public class LocationMap implements ILocationResolver { startOffset= getSequenceNumberForOffset(startOffset); condOffset= getSequenceNumberForOffset(condOffset); condEndOffset= getSequenceNumberForOffset(condEndOffset); - // compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset); + // not using endOffset, compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset); fDirectives.add(new ASTError(fTranslationUnit, startOffset, condOffset, condEndOffset)); } @@ -255,7 +257,7 @@ public class LocationMap implements ILocationResolver { startOffset= getSequenceNumberForOffset(startOffset); condOffset= getSequenceNumberForOffset(condOffset); condEndOffset= getSequenceNumberForOffset(condEndOffset); - // compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset); + // not using endOffset, compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset); fDirectives.add(new ASTPragma(fTranslationUnit, startOffset, condOffset, condEndOffset)); } @@ -263,7 +265,7 @@ public class LocationMap implements ILocationResolver { startOffset= getSequenceNumberForOffset(startOffset); condOffset= getSequenceNumberForOffset(condOffset); condEndOffset= getSequenceNumberForOffset(condEndOffset); - // compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset); + // not using endOffset, compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset); fDirectives.add(new ASTIfdef(fTranslationUnit, startOffset, condOffset, condEndOffset, isActive)); } @@ -271,7 +273,7 @@ public class LocationMap implements ILocationResolver { startOffset= getSequenceNumberForOffset(startOffset); condOffset= getSequenceNumberForOffset(condOffset); condEndOffset= getSequenceNumberForOffset(condEndOffset); - // compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset); + // not using endOffset, compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset); fDirectives.add(new ASTIfndef(fTranslationUnit, startOffset, condOffset, condEndOffset, isActive)); } @@ -279,7 +281,7 @@ public class LocationMap implements ILocationResolver { startOffset= getSequenceNumberForOffset(startOffset); condOffset= getSequenceNumberForOffset(condOffset); condEndOffset= getSequenceNumberForOffset(condEndOffset); - // compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset); + // not using endOffset, compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset); fDirectives.add(new ASTIf(fTranslationUnit, startOffset, condOffset, condEndOffset, isActive)); } @@ -303,8 +305,10 @@ public class LocationMap implements ILocationResolver { startOffset= getSequenceNumberForOffset(startOffset); nameOffset= getSequenceNumberForOffset(nameOffset); nameEndOffset= getSequenceNumberForOffset(nameEndOffset); -// endOffset= getSequenceNumberForOffset(endOffset); - fDirectives.add(new ASTUndef(fTranslationUnit, name, startOffset, nameOffset, nameEndOffset, definition)); + // not using endOffset, compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset); + final ASTUndef undef = new ASTUndef(fTranslationUnit, name, startOffset, nameOffset, nameEndOffset, definition); + fDirectives.add(undef); + addMacroReference(definition, undef.getMacroName()); } public void setRootNode(IASTTranslationUnit root) { @@ -341,15 +345,77 @@ public class LocationMap implements ILocationResolver { } public String getContainingFilename(int sequenceNumber) { - LocationCtx ctx= fRootContext.ctxForNumberRange(sequenceNumber, 1); + LocationCtx ctx= fRootContext.findSurroundingContext(sequenceNumber, 1); return new String(ctx.getFilePath()); } public IASTFileLocation getMappedFileLocation(int sequenceNumber, int length) { - return fRootContext.fileLocationForNumberRange(sequenceNumber, length); + return fRootContext.findMappedFileLocation(sequenceNumber, length); + } + + public char[] getUnpreprocessedSignature(IASTFileLocation loc) { + if (loc instanceof ASTFileLocation) { + return ((ASTFileLocation) loc).getSource(); + } + return CharArrayUtils.EMPTY; } - public IASTPreprocessorMacroDefinition[] getMacroDefinitions() { + public IASTNodeLocation[] getLocations(int sequenceNumber, int length) { + ArrayList result= new ArrayList(); + fRootContext.collectLocations(sequenceNumber, length, result); + return (IASTNodeLocation[]) result.toArray(new IASTNodeLocation[result.size()]); + } + + public IASTNode findSurroundingPreprocessorNode(int sequenceNumber, int length) { + int lower=0; + int upper= fDirectives.size()-1; + while(lower <= upper) { + int middle= (lower+upper)/2; + ASTPreprocessorNode node= (ASTPreprocessorNode) fDirectives.get(middle); + final int nodeSequenceNumber= node.getOffset(); + if (nodeSequenceNumber <= sequenceNumber) { + final int nodeEndSequenceNumber= nodeSequenceNumber + node.getLength(); + if (sequenceNumber+length <= nodeEndSequenceNumber) { + return node.findSurroundingNode(sequenceNumber, length); + } + else { + lower= middle+1; + } + } + else { + upper= middle-1; + } + } + return null; + } + + public int getSequenceNumberForFileOffset(String filePath, int fileOffset) { + LocationCtx ctx= fRootContext; + if (filePath != null) { + LinkedList contexts= new LinkedList(); + while(ctx != null) { + if (ctx instanceof LocationCtxFile) { + if (filePath.equals(ctx.getFilePath())) { + break; + } + } + contexts.addAll(ctx.getChildren()); + if (contexts.isEmpty()) { + ctx= null; + } + else { + ctx= (LocationCtx) contexts.removeFirst(); + } + } + } + if (ctx != null) { + return ctx.getSequenceNumberForOffset(fileOffset, true); + } + return -1; + } + + + public IASTPreprocessorMacroDefinition[] getMacroDefinitions() { ArrayList result= new ArrayList(); for (Iterator iterator = fDirectives.iterator(); iterator.hasNext();) { Object directive= iterator.next(); @@ -389,22 +455,27 @@ public class LocationMap implements ILocationResolver { public IASTName[] getDeclarations(IMacroBinding binding) { + IASTPreprocessorMacroDefinition def = getMacroDefinition(binding); + return def == null ? EMPTY_NAMES : new IASTName[] {def.getName()}; + } + + IASTPreprocessorMacroDefinition getMacroDefinition(IMacroBinding binding) { if (fMacroDefinitionMap == null) { fMacroDefinitionMap= new IdentityHashMap(); IASTPreprocessorMacroDefinition[] defs= getMacroDefinitions(); for (int i = 0; i < defs.length; i++) { - final IASTName name = defs[i].getName(); + final IASTPreprocessorMacroDefinition def = defs[i]; + final IASTName name = def.getName(); if (name != null) { - fMacroDefinitionMap.put(name.getBinding(), name); + fMacroDefinitionMap.put(name.getBinding(), def); } } } - IASTName name= (IASTName) fMacroDefinitionMap.get(binding); - return name == null ? EMPTY_NAMES : new IASTName[] {name}; + return (IASTPreprocessorMacroDefinition) fMacroDefinitionMap.get(binding); } public IASTName[] getReferences(IMacroBinding binding) { - List list= (List) fMacroExpansions.get(binding); + List list= (List) fMacroReferences.get(binding); if (list == null) { return EMPTY_NAMES; } @@ -418,36 +489,19 @@ public class LocationMap implements ILocationResolver { public void cleanup() { } - // stuff to remove from ILocationResolver - public IASTName[] getMacroExpansions() { - throw new UnsupportedOperationException(); - } - - // mstodo- locations - public IASTFileLocation flattenLocations(IASTNodeLocation[] locations) { - if (locations.length != 1 || !(locations[0] instanceof IASTFileLocation)) { - throw new IllegalArgumentException(); - } - return (IASTFileLocation) locations[0]; - } - // mstodo- locations - public IASTNodeLocation[] getLocations(int offset, int length) { - return new IASTNodeLocation[] {getMappedFileLocation(offset, length)}; - } public ASTPreprocessorSelectionResult getPreprocessorNode(String path, int offset, int length) { throw new UnsupportedOperationException(); } // mstodo- locations public char[] getUnpreprocessedSignature(IASTNodeLocation[] locations) { - switch(locations.length) { - case 0: return CharArrayUtils.EMPTY; - case 1: break; - default: throw new IllegalArgumentException(); - } - if (!(locations[0] instanceof ASTFileLocation)) { - throw new IllegalArgumentException(); - } - ASTFileLocation floc= (ASTFileLocation) locations[0]; - return floc.getSource(); + throw new UnsupportedOperationException(); + } + // mstodo- scanner removal + public IASTFileLocation flattenLocations(IASTNodeLocation[] locations) { + throw new UnsupportedOperationException(); + } + // mstodo- scanner removal + public IASTName[] getMacroExpansions() { + throw new UnsupportedOperationException(); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroDefinitionParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroDefinitionParser.java index c3125f3e7fd..08cee06a988 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroDefinitionParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroDefinitionParser.java @@ -23,6 +23,11 @@ import org.eclipse.cdt.core.parser.util.CharArrayUtils; * @since 5.0 */ class MacroDefinitionParser { + private static final int ORIGIN_PREPROCESSOR_DIRECTIVE = OffsetLimitReachedException.ORIGIN_PREPROCESSOR_DIRECTIVE; + + /** + * Exception for reporting problems while parsing a macro definition. + */ static class InvalidMacroDefinitionException extends Exception { public char[] fName; public int fStartOffset; @@ -34,7 +39,25 @@ class MacroDefinitionParser { } } - private static final int ORIGIN_PREPROCESSOR_DIRECTIVE = OffsetLimitReachedException.ORIGIN_PREPROCESSOR_DIRECTIVE; + /** + * Token used for macro parameters found in the replacement list. + */ + static class TokenParameterReference extends TokenWithImage { + private final int fIndex; + + public TokenParameterReference(int type, int idx, Object source, int offset, int endOffset, char[] name) { + super(type, source, offset, endOffset, name); + fIndex= idx; + } + + public int getIndex() { + return fIndex; + } + + public String toString() { + return "[" + fIndex + "]"; //$NON-NLS-1$ //$NON-NLS-2$ + } + } private int fHasVarArgs; private int fExpansionOffset; @@ -208,7 +231,7 @@ class MacroDefinitionParser { final char[] image = candidate.getCharImage(); int idx= CharArrayUtils.indexOf(image, paramList); if (idx >= 0) { - candidate= new PlaceHolderToken(CPreprocessor.tMACRO_PARAMETER, idx, lexer.getSource(), candidate.getOffset(), candidate.getEndOffset(), paramList[idx]); + candidate= new TokenParameterReference(CPreprocessor.tMACRO_PARAMETER, idx, lexer.getSource(), candidate.getOffset(), candidate.getEndOffset(), paramList[idx]); needParam= false; } else { @@ -225,6 +248,7 @@ class MacroDefinitionParser { break; case IToken.tPOUND: needParam= paramList != null; + needAnotherToken= null; break; case IToken.tPOUNDPOUND: if (needParam || isFirst) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpander.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpander.java index 7aaf72cbc84..1820c49d7f2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpander.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpander.java @@ -20,6 +20,7 @@ import org.eclipse.cdt.core.parser.OffsetLimitReachedException; import org.eclipse.cdt.core.parser.util.CharArrayObjectMap; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions; +import org.eclipse.cdt.internal.core.parser.scanner.MacroDefinitionParser.TokenParameterReference; /** * Utility class to perform macro expansion. @@ -220,10 +221,10 @@ public class MacroExpander { final Object s2= t.fSource; if (s1 == s2 && s1 != null) { if (l.getEndOffset() == t.getOffset()) { - target.append(new SimpleToken(CPreprocessor.tNOSPACE, null, 0, 0)); + target.append(new Token(CPreprocessor.tNOSPACE, null, 0, 0)); } else { - target.append(new SimpleToken(CPreprocessor.tSPACE, null, 0, 0)); + target.append(new Token(CPreprocessor.tSPACE, null, 0, 0)); } } } @@ -350,7 +351,7 @@ public class MacroExpander { switch(t.getType()) { case CPreprocessor.tMACRO_PARAMETER: - int idx= ((PlaceHolderToken) t).getIndex(); + int idx= ((TokenParameterReference) t).getIndex(); if (idx < args.length) { // be defensive addSpacemarker(l, t, result); // start argument replacement TokenList arg= clone(pasteNext ? args[idx] : expandedArgs[idx]); @@ -373,7 +374,7 @@ public class MacroExpander { StringBuffer buf= new StringBuffer(); buf.append('"'); if (n != null && n.getType() == CPreprocessor.tMACRO_PARAMETER) { - idx= ((PlaceHolderToken) n).getIndex(); + idx= ((TokenParameterReference) n).getIndex(); if (idx < args.length) { // be defensive stringify(args[idx], buf); } @@ -386,7 +387,7 @@ public class MacroExpander { final char[] image= new char[length]; buf.getChars(0, length, image, 0); - Token generated= new ImageToken(IToken.tSTRING, null, 0, 0, image); + Token generated= new TokenWithImage(IToken.tSTRING, null, 0, 0, image); if (pasteNext) { // start token paste, same as start stringify pasteArg1= generated; } @@ -402,7 +403,7 @@ public class MacroExpander { TokenList rest= null; if (n != null) { if (n.getType() == CPreprocessor.tMACRO_PARAMETER) { - idx= ((PlaceHolderToken) n).getIndex(); + idx= ((TokenParameterReference) n).getIndex(); if (idx < args.length) { // be defensive TokenList arg= clone(args[idx]); pasteArg2= arg.first(); @@ -417,7 +418,7 @@ public class MacroExpander { pasteArg1= pasteArg2= null; } } - if (pasteArg2 != null) { + if (pasteArg2 != null && arg.first() != arg.last()) { rest= arg; rest.removeFirst(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContextMacroExpansion.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContextMacroExpansion.java index 72492293210..1f7ea989b95 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContextMacroExpansion.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContextMacroExpansion.java @@ -13,7 +13,7 @@ package org.eclipse.cdt.internal.core.parser.scanner; public class ScannerContextMacroExpansion extends ScannerContext { - private static final Token END_TOKEN = new SimpleToken(Lexer.tEND_OF_INPUT, null, 0, 0); + private static final Token END_TOKEN = new Token(Lexer.tEND_OF_INPUT, null, 0, 0); private Token fTokens; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContextPPDirective.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContextPPDirective.java index 9a90db40d7c..68d4a1fba46 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContextPPDirective.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContextPPDirective.java @@ -70,7 +70,7 @@ public final class ScannerContextPPDirective extends ScannerContext { private Token convertToken(Token t) { switch (t.getType()) { case Lexer.tNEWLINE: - t= new SimpleToken(Lexer.tEND_OF_INPUT, null, t.getEndOffset(), t.getEndOffset()); + t= new Token(Lexer.tEND_OF_INPUT, null, t.getEndOffset(), t.getEndOffset()); break; case IToken.tIDENTIFIER: if (fConvertDefinedToken && CharArrayUtils.equals(Keywords.cDEFINED, t.getCharImage())) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Token.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Token.java index ee18f8415db..4fdd9ab4bd5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Token.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/Token.java @@ -17,7 +17,7 @@ import org.eclipse.cdt.core.parser.IToken; * them on to the parsers. * @since 5.0 */ -public abstract class Token implements IToken, Cloneable { +public class Token implements IToken, Cloneable { private int fKind; private int fOffset; private int fEndOffset; @@ -65,10 +65,8 @@ public abstract class Token implements IToken, Cloneable { fEndOffset= endOffset; } - public abstract char[] getCharImage(); - - final public boolean hasGap(Token t) { - return fSource == t.fSource && fEndOffset != t.getOffset(); + public char[] getCharImage() { + return TokenUtil.getImage(getType()); } public String toString() { @@ -90,7 +88,7 @@ public abstract class Token implements IToken, Cloneable { return null; } } - + public char[] getFilename() { // mstodo- parser removal throw new UnsupportedOperationException(); @@ -116,79 +114,3 @@ public abstract class Token implements IToken, Cloneable { throw new UnsupportedOperationException(); } } - -class SimpleToken extends Token { - public SimpleToken(int kind, Object source, int offset, int endOffset) { - super(kind, source, offset, endOffset); - } - - public char[] getCharImage() { - return TokenUtil.getImage(getType()); - } -} - -class PlaceHolderToken extends ImageToken { - private final int fIndex; - - public PlaceHolderToken(int type, int idx, Object source, int offset, int endOffset, char[] name) { - super(type, source, offset, endOffset, name); - fIndex= idx; - } - - public int getIndex() { - return fIndex; - } - - public String toString() { - return "[" + fIndex + "]"; //$NON-NLS-1$ //$NON-NLS-2$ - } -} - -class DigraphToken extends Token { - public DigraphToken(int kind, Object source, int offset, int endOffset) { - super(kind, source, offset, endOffset); - } - - public char[] getCharImage() { - return TokenUtil.getDigraphImage(getType()); - } -} - -class ImageToken extends Token { - private char[] fImage; - - public ImageToken(int kind, Object source, int offset, int endOffset, char[] image) { - super(kind, source, offset, endOffset); - fImage= image; - } - - public char[] getCharImage() { - return fImage; - } -} - -class SourceImageToken extends Token { - private char[] fSourceImage; - private char[] fImage; - - public SourceImageToken(int kind, Object source, int offset, int endOffset, char[] sourceImage) { - super(kind, source, offset, endOffset); - fSourceImage= sourceImage; - } - - public char[] getCharImage() { - if (fImage == null) { - final int length= getLength(); - fImage= new char[length]; - System.arraycopy(fSourceImage, getOffset(), fImage, 0, length); - } - return fImage; - } - - public void setOffset(int offset, int endOffset) { - getCharImage(); - super.setOffset(offset, endOffset); - } -} - - diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenForDigraph.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenForDigraph.java new file mode 100644 index 00000000000..340cb859967 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenForDigraph.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2007 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.parser.scanner; + +/** + * Tokens for digraphs simply have a different image. + * @since 5.0 + */ +public class TokenForDigraph extends Token { + public TokenForDigraph(int kind, Object source, int offset, int endOffset) { + super(kind, source, offset, endOffset); + } + + public char[] getCharImage() { + return TokenUtil.getDigraphImage(getType()); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenWithImage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenWithImage.java new file mode 100644 index 00000000000..bf58d015537 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenWithImage.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2007 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.parser.scanner; + +public class TokenWithImage extends Token { + private char[] fImage; + + public TokenWithImage(int kind, Object source, int offset, int endOffset, char[] image) { + super(kind, source, offset, endOffset); + fImage= image; + } + + public char[] getCharImage() { + return fImage; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/TokenFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/TokenFactory.java index 36cabb86dfd..337c29f0fcd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/TokenFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/TokenFactory.java @@ -1,18 +1,21 @@ /******************************************************************************* - * Copyright (c) 2005 IBM Corporation and others. + * Copyright (c) 2005, 2007 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 * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM Rational Software - Initial API and implementation + * IBM Rational Software - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.parser.token; import java.util.Arrays; +import java.util.Iterator; import java.util.List; +import org.eclipse.cdt.core.parser.ISourceElementRequestor; import org.eclipse.cdt.core.parser.IToken; import org.eclipse.cdt.core.parser.ITokenDuple; @@ -20,27 +23,125 @@ import org.eclipse.cdt.core.parser.ITokenDuple; * @author johnc */ public class TokenFactory { - protected static final char[] EMPTY_CHAR_ARRAY = "".toCharArray(); //$NON-NLS-1$ + + private static class TokenWrapper implements ITokenDuple { + private final IToken fToken; + + public TokenWrapper(IToken t) { + fToken= t; + } + + public String toString() { + return fToken.toString(); + } + public boolean contains(ITokenDuple duple) { + return fToken == duple.getFirstToken() && fToken == duple.getLastToken(); + } + public char[] extractNameFromTemplateId(){ + return fToken.getCharImage(); + } + public int findLastTokenType(int t) { + return fToken.getType() == t ? 0 : -1; + } + public IToken getFirstToken() { + return fToken; + } + public ITokenDuple getLastSegment() { + return this; + } + public IToken getLastToken() { + return fToken; + } + public ITokenDuple getLeadingSegments() { + return null; + } + public int getSegmentCount() { + return 1; + } + public int getStartOffset() { + return fToken.getOffset(); + } + public ITokenDuple getSubrange(int startIndex, int endIndex) { + if( startIndex == 0 && endIndex == 0 ) return this; + return null; + } + public List[] getTemplateIdArgLists() { + return null; + } + public IToken getToken(int index) { + if( index == 0 ) return fToken; + return null; + } + public boolean isIdentifier() { + return ( fToken.getType() == IToken.tIDENTIFIER ); + } + + public Iterator iterator() { + return new Iterator() { + private boolean hasNext = true; + public void remove() { + throw new UnsupportedOperationException(); + } + public boolean hasNext() { + return hasNext; + } + public Object next() { + hasNext = false; + return fToken; + } + }; + } + public int length() { + return 1; + } + public boolean syntaxOfName() { + return isIdentifier(); + } + public String[] toQualifiedName() { + return new String[] {fToken.getImage()}; + } + public void freeReferences() { + } + public void acceptElement(ISourceElementRequestor requestor) { + } + public ITokenDuple[] getSegments() { + return new ITokenDuple[] {this}; + } + public int getEndOffset() { + return fToken.getEndOffset(); + } + public char[] getFilename() { + return fToken.getFilename(); + } + public int getLineNumber() { + return fToken.getLineNumber(); + } + public char[] toCharArray() { + return fToken.getCharImage(); + } + } public static IToken createStandAloneToken( int type, String image ) { return new ImagedToken( type, image.toCharArray(), 0, EMPTY_CHAR_ARRAY, 0); } - public static ITokenDuple createTokenDuple( IToken first, IToken last ) - { - if( (first == last) && ( first instanceof ITokenDuple )) return (ITokenDuple) first; + public static ITokenDuple createTokenDuple(IToken first, IToken last) { + if (first == last) { + if (first instanceof ITokenDuple) { + return (ITokenDuple) first; + } + return new TokenWrapper(first); + } return new BasicTokenDuple( first, last ); } - public static ITokenDuple createTokenDuple( IToken first, IToken last, List templateArgLists ) - { - if( (first == last) && ( templateArgLists == null ) && ( first instanceof ITokenDuple )) - return (ITokenDuple) first; - if( templateArgLists != null && !templateArgLists.isEmpty()) - return new TemplateTokenDuple( first, last, templateArgLists ); - return new BasicTokenDuple( first, last ); + public static ITokenDuple createTokenDuple(IToken first, IToken last, List templateArgLists) { + if (templateArgLists == null || templateArgLists.isEmpty()) { + return createTokenDuple(first, last); + } + return new TemplateTokenDuple( first, last, templateArgLists ); } public static ITokenDuple createTokenDuple( ITokenDuple firstDuple, ITokenDuple secondDuple ){