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 IASTNodeLocation
s 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-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 ){