/******************************************************************************* * Copyright (c) 2000, 2009 QNX Software Systems 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: * QNX Software Systems - Initial API and implementation * Anton Leherbauer (Wind River Systems) * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.model; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.IFunctionDeclaration; import org.eclipse.cdt.core.model.IMember; import org.eclipse.cdt.core.model.IOpenable; import org.eclipse.cdt.core.model.ISourceManipulation; import org.eclipse.cdt.core.model.ISourceRange; import org.eclipse.cdt.core.model.ISourceReference; import org.eclipse.cdt.core.model.ITemplate; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.internal.core.util.MementoTokenizer; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; /** * Abstract class for C elements which implement ISourceReference. */ public class SourceManipulation extends Parent implements ISourceManipulation, ISourceReference { /** * An empty list of Strings */ protected static final String[] fgEmptyStrings = {}; private boolean fIsActive= true; private short fIndex= 0; public SourceManipulation(ICElement parent, String name, int type) { super(parent, name, type); } /** * @see ISourceManipulation */ public void copy(ICElement container, ICElement sibling, String rename, boolean force, IProgressMonitor monitor) throws CModelException { if (container == null) { throw new IllegalArgumentException(CoreModelMessages.getString("operation.nullContainer")); //$NON-NLS-1$ } ICElement[] elements= new ICElement[] {this}; ICElement[] containers= new ICElement[] {container}; ICElement[] siblings= null; if (sibling != null) { siblings= new ICElement[] {sibling}; } String[] renamings= null; if (rename != null) { renamings= new String[] {rename}; } getCModel().copy(elements, containers, siblings, renamings, force, monitor); } /** * @see ISourceManipulation */ public void delete(boolean force, IProgressMonitor monitor) throws CModelException { ICElement[] elements = new ICElement[] {this}; getCModel().delete(elements, force, monitor); } /** * @see ISourceManipulation */ public void move(ICElement container, ICElement sibling, String rename, boolean force, IProgressMonitor monitor) throws CModelException { if (container == null) { throw new IllegalArgumentException(CoreModelMessages.getString("operation.nullContainer")); //$NON-NLS-1$ } ICElement[] elements= new ICElement[] {this}; ICElement[] containers= new ICElement[] {container}; ICElement[] siblings= null; if (sibling != null) { siblings= new ICElement[] {sibling}; } String[] renamings= null; if (rename != null) { renamings= new String[] {rename}; } getCModel().move(elements, containers, siblings, renamings, force, monitor); } /** * @see ISourceManipulation */ public void rename(String name, boolean force, IProgressMonitor monitor) throws CModelException { if (name == null) { throw new IllegalArgumentException("element.nullName"); //$NON-NLS-1$ } ICElement[] elements= new ICElement[] {this}; ICElement[] dests= new ICElement[] {this.getParent()}; String[] renamings= new String[] {name}; getCModel().rename(elements, dests, renamings, force, monitor); } /** * @see IMember */ public ITranslationUnit getTranslationUnit() { try { return getSourceManipulationInfo().getTranslationUnit(); } catch (CModelException e) { return null; } } /** * Elements within compilation units and class files have no * corresponding resource. * * @see ICElement */ public IResource getCorrespondingResource() throws CModelException { return null; } /** * Returns the first parent of the element that is an instance of * IOpenable. */ @Override public IOpenable getOpenableParent() { ICElement current = getParent(); while (current != null){ if (current instanceof IOpenable){ return (IOpenable) current; } current = current.getParent(); } return null; } /** * @see ISourceReference */ public String getSource() throws CModelException { return getSourceManipulationInfo().getSource(); } /** * @see ISourceReference */ public ISourceRange getSourceRange() throws CModelException { return getSourceManipulationInfo().getSourceRange(); } /** * @see ICElement */ @Override public IResource getUnderlyingResource() { return getParent().getUnderlyingResource(); } @Override public IResource getResource() { return null; } @Override protected CElementInfo createElementInfo () { return new SourceManipulationInfo(this); } protected SourceManipulationInfo getSourceManipulationInfo() throws CModelException { return (SourceManipulationInfo)getElementInfo(); } public boolean isIdentical(SourceManipulation other) throws CModelException{ return (this.equals(other) && (this.getSourceManipulationInfo().hasSameContentsAs(other.getSourceManipulationInfo()))); } /* * @see CElement#generateInfos */ @Override protected void generateInfos(CElementInfo info, Map<ICElement, CElementInfo> newElements, IProgressMonitor pm) throws CModelException { Openable openableParent = (Openable)getOpenableParent(); if (openableParent == null) { return; } newElements.put(this, info); CElementInfo openableParentInfo = (CElementInfo) CModelManager.getDefault().getInfo(openableParent); if (openableParentInfo == null) { openableParent.generateInfos(openableParent.createElementInfo(), newElements, pm); } } public void setPos(int startPos, int length) { try { getSourceManipulationInfo().setPos(startPos, length); } catch (CModelException e) { // } } public void setIdPos(int startPos, int length) { try { getSourceManipulationInfo().setIdPos(startPos, length); } catch (CModelException e) { // } } public void setLines(int startLine, int endLine) { try { getSourceManipulationInfo().setLines(startLine, endLine); } catch (CModelException e) { // } } /* * @see CElement */ @Override public ICElement getHandleFromMemento(String token, MementoTokenizer memento) { switch (token.charAt(0)) { case CEM_SOURCEELEMENT: if (!memento.hasMoreTokens()) return this; token= memento.nextToken(); // element name final String elementName; if (token.charAt(0) != CEM_ELEMENTTYPE) { elementName= token; if (!memento.hasMoreTokens()) return null; token= memento.nextToken(); } else { // anonymous elementName= ""; //$NON-NLS-1$ } // element type if (token.charAt(0) != CEM_ELEMENTTYPE || !memento.hasMoreTokens()) { return null; } String typeString= memento.nextToken(); int elementType; try { elementType= Integer.parseInt(typeString); } catch (NumberFormatException nfe) { CCorePlugin.log(nfe); return null; } token= null; // optional: parameters String[] mementoParams= {}; if (memento.hasMoreTokens()) { List<String> params= new ArrayList<String>(); do { token= memento.nextToken(); if (token.charAt(0) != CEM_PARAMETER) { break; } if (!memento.hasMoreTokens()) { params.add(""); //$NON-NLS-1$ token= null; break; } params.add(memento.nextToken()); token= null; } while (memento.hasMoreTokens()); mementoParams= params.toArray(new String[params.size()]); } CElement element= null; ICElement[] children; try { children= getChildren(); } catch (CModelException exc) { CCorePlugin.log(exc); return null; } switch (elementType) { case ICElement.C_FUNCTION: case ICElement.C_FUNCTION_DECLARATION: case ICElement.C_METHOD: case ICElement.C_METHOD_DECLARATION: case ICElement.C_TEMPLATE_FUNCTION: case ICElement.C_TEMPLATE_FUNCTION_DECLARATION: case ICElement.C_TEMPLATE_METHOD: case ICElement.C_TEMPLATE_METHOD_DECLARATION: for (ICElement element2 : children) { if (elementType == element2.getElementType() && elementName.equals(element2.getElementName())) { assert element2 instanceof IFunctionDeclaration; String[] functionParams= ((IFunctionDeclaration)element2).getParameterTypes(); if (Arrays.equals(functionParams, mementoParams)) { element= (CElement) element2; break; } } } break; case ICElement.C_TEMPLATE_CLASS: case ICElement.C_TEMPLATE_STRUCT: case ICElement.C_TEMPLATE_UNION: for (ICElement element2 : children) { if (elementType == element2.getElementType() && elementName.equals(element2.getElementName())) { assert element2 instanceof ITemplate; String[] templateParams= ((ITemplate)element2).getTemplateParameterTypes(); if (Arrays.equals(templateParams, mementoParams)) { element= (CElement) element2; break; } } } break; default: for (ICElement element2 : children) { if (elementType == element2.getElementType() && elementName.equals(element2.getElementName())) { element= (CElement) element2; break; } } break; } if (element != null) { if (token != null) { return element.getHandleFromMemento(token, memento); } else { return element.getHandleFromMemento(memento); } } } return null; } @Override public void getHandleMemento(StringBuilder buff) { ((CElement)getParent()).getHandleMemento(buff); buff.append(getHandleMementoDelimiter()); escapeMementoName(buff, getElementName()); buff.append(CEM_ELEMENTTYPE); buff.append(Integer.toString(getElementType())); } @Override protected char getHandleMementoDelimiter() { return CElement.CEM_SOURCEELEMENT; } public boolean isActive() { return fIsActive; } public int getIndex() { return fIndex; } public void setActive(boolean active) { fIsActive= active; } public void setIndex(int i) { fIndex= (short) i; } @Override public int hashCode() { return Util.combineHashCodes(fIndex, super.hashCode()); } @Override public boolean equals(Object other) { if (other instanceof ISourceReference) { if (fIndex != ((ISourceReference) other).getIndex()) return false; } return super.equals(other); } }