blob: 8f3aa29586d9d64d50b09683eaaba32cb1f2bf83 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2011 Google, 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:
* Sergey Prigogin (Google) - initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
import java.util.LinkedHashSet;
import java.util.Set;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
import org.eclipse.cdt.internal.core.pdom.db.Database;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
import org.eclipse.core.runtime.CoreException;
/**
* Represents "using" declaration in PDOM. A single "using" declaration resolving to multiple
* objects, e.g. functions with the same name but different signatures, is represented by multiple
* chained PDOMCPPUsingDeclaration records.
*
* @see ICPPUsingDeclaration
*/
class PDOMCPPUsingDeclaration extends PDOMCPPBinding implements ICPPUsingDeclaration {
private static final int TARGET_BINDING = PDOMCPPBinding.RECORD_SIZE + 0;
// Using declarations for functions may have multiple delegates. We model such case
// by creating a chain of PDOMCPPUsingDeclaration objects linked by NEXT_DELEGATE field.
private static final int NEXT_DELEGATE = PDOMCPPBinding.RECORD_SIZE + 4;
@SuppressWarnings("hiding")
protected static final int RECORD_SIZE = PDOMCPPBinding.RECORD_SIZE + 8;
private volatile IBinding[] delegates;
public PDOMCPPUsingDeclaration(PDOMLinkage linkage, PDOMNode parent, ICPPUsingDeclaration using)
throws CoreException {
super(linkage, parent, using.getNameCharArray());
final Database db = getDB();
final char[] name = using.getNameCharArray();
Set<PDOMBinding> targets= new LinkedHashSet<PDOMBinding>();
PDOMCPPUsingDeclaration last= null;
for (IBinding delegate : using.getDelegates()) {
PDOMBinding target = getLinkage().adaptBinding(delegate);
if (target != null && targets.add(target)) {
if (last == null) {
setTargetBinding(linkage, target);
last= this;
} else {
PDOMCPPUsingDeclaration next= new PDOMCPPUsingDeclaration(linkage, parent, name);
next.setTargetBinding(linkage, target);
db.putRecPtr(last.getRecord() + NEXT_DELEGATE, next.record);
last= next;
}
}
}
}
public PDOMCPPUsingDeclaration(PDOMLinkage linkage, long record) {
super(linkage, record);
}
private PDOMCPPUsingDeclaration(PDOMLinkage linkage, PDOMNode parent, char[] name) throws CoreException {
super(linkage, parent, name);
}
private void setTargetBinding(PDOMLinkage linkage, PDOMBinding delegate) throws CoreException {
getDB().putRecPtr(record + TARGET_BINDING, delegate != null ? delegate.getRecord() : 0);
}
@Override
protected int getRecordSize() {
return RECORD_SIZE;
}
@Override
public int getNodeType() {
return IIndexCPPBindingConstants.CPP_USING_DECLARATION;
}
public IBinding[] getDelegates() {
if (delegates == null) {
delegates = new IBinding[1];
int i = 0;
PDOMCPPUsingDeclaration alias = this;
try {
do {
IBinding delegate = alias.getBinding();
if (delegate != null) {
delegates= (IBinding[]) ArrayUtil.append(IBinding.class, delegates, i++, delegate);
}
} while ((alias = alias.getNext()) != null);
} catch (CoreException e) {
CCorePlugin.log(e);
}
delegates = (IBinding[]) ArrayUtil.trim(IBinding.class, delegates);
}
return delegates;
}
private PDOMCPPUsingDeclaration getNext() throws CoreException {
long nextRecord = getDB().getRecPtr(record + NEXT_DELEGATE);
return nextRecord != 0 ? new PDOMCPPUsingDeclaration(getLinkage(), nextRecord) : null;
}
private IBinding getBinding() {
try {
return (IBinding) getLinkage().getNode(
getPDOM().getDB().getRecPtr(record + TARGET_BINDING));
} catch (CoreException e) {
CCorePlugin.log(e);
}
return null;
}
}