/*******************************************************************************
* Copyright (c) 2007, 2008 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.IASTImageLocation;
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
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 final ImageLocationInfo[] fLocationInfos;
private ASTMacroReferenceName fExpansionName;
public LocationCtxMacroExpansion(LocationMap map, LocationCtxContainer parent, int parentOffset, int parentEndOffset,
int sequenceNumber, int length, ImageLocationInfo[] imageLocations, ASTMacroReferenceName expansionName) {
super(parent, parentOffset, parentEndOffset, sequenceNumber);
fLocationMap= map;
fLength= length;
fLocationInfos= imageLocations;
fExpansionName= expansionName;
if (expansionName.getParent() instanceof ASTMacroExpansion == false) {
throw new IllegalArgumentException(expansionName.toString() + " is not a macro expansion name"); //$NON-NLS-1$
}
}
@Override
public int getSequenceLength() {
return fLength;
}
@Override
public boolean collectLocations(int start, int length, ArrayList<IASTNodeLocation> 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 ASTMacroExpansion getExpansion() {
return (ASTMacroExpansion) fExpansionName.getParent();
}
public ASTMacroReferenceName getMacroReference() {
return fExpansionName;
}
public IASTPreprocessorMacroDefinition getMacroDefinition() {
return fLocationMap.getMacroDefinition((IMacroBinding) fExpansionName.getBinding());
}
@Override
public LocationCtxMacroExpansion findEnclosingMacroExpansion(int sequenceNumber, int length) {
return this;
}
public IASTImageLocation getImageLocation(int offset, int length) {
if (length == 0) {
return null;
}
final int end= offset+length;
int nextToCheck= offset;
ImageLocationInfo firstInfo= null;
ImageLocationInfo lastInfo= null;
for (ImageLocationInfo info : fLocationInfos) {
if (info.fTokenOffsetInExpansion == nextToCheck) {
if (firstInfo == null || lastInfo == null) {
firstInfo= lastInfo= info;
} else if (lastInfo.canConcatenate(info)) {
lastInfo= info;
} else {
return null;
}
if (++nextToCheck == end) {
return firstInfo.createLocation(fLocationMap, lastInfo);
}
} else if (info.fTokenOffsetInExpansion > nextToCheck) {
return null;
}
}
return null;
}
public ASTPreprocessorName[] getNestedMacroReferences() {
return fLocationMap.getNestedMacroReferences((ASTMacroExpansion) fExpansionName.getParent());
}
@Override
public String toString() {
return "Expansion of " + fExpansionName.toString(); //$NON-NLS-1$
}
}