blob: 5f2cd5a30a967466bd43005e732a6218b1277005 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2016 IBM Corporation and others.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
*******************************************************************************/
package org.eclipse.dltk.internal.core;
import java.util.HashMap;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.dltk.core.IBuffer;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.IOpenable;
import org.eclipse.dltk.core.IParent;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.ISourceRange;
import org.eclipse.dltk.core.ISourceReference;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.core.WorkingCopyOwner;
import org.eclipse.dltk.internal.core.util.MementoTokenizer;
public abstract class SourceRefElement extends ModelElement implements
ISourceReference {
/*
* A count to uniquely identify this element in the case that a duplicate
* named element exists. For example, if there are two fields in a
* compilation unit with the same name, the occurrence count is used to
* distinguish them. The occurrence count starts at 1 (thus the first
* occurrence is occurrence 1, not occurrence 0).
*/
public int occurrenceCount = 1;
protected SourceRefElement(ModelElement parent)
throws IllegalArgumentException {
super(parent);
}
@Override
protected Object createElementInfo() {
// do not used for source elements
return null;
}
@Override
protected void generateInfos(Object info, HashMap newElements,
IProgressMonitor pm) throws ModelException {
Openable openableParent = (Openable) getOpenableParent();
if (openableParent == null)
return;
ModelElementInfo openableParentInfo = (ModelElementInfo) ModelManager
.getModelManager().getInfo(openableParent);
if (openableParentInfo == null) {
openableParent.generateInfos(openableParent.createElementInfo(),
newElements, pm);
}
}
/**
* Return the first instance of IOpenable in the hierarchy of this type
* (going up the hierarchy from this type);
*/
@Override
public IOpenable getOpenableParent() {
IModelElement current = getParent();
while (current != null) {
if (current instanceof IOpenable) {
return (IOpenable) current;
}
current = current.getParent();
}
return null;
}
@Override
public IResource getResource() {
return getParent().getResource();
}
/**
* @see ISourceReference
*/
@Override
public ISourceRange getSourceRange() throws ModelException {
SourceRefElementInfo info = (SourceRefElementInfo) getElementInfo();
if (info != null)
return info.getSourceRange();
return null;
}
@Override
public IPath getPath() {
return getParent().getPath();
}
@Override
public IResource getUnderlyingResource() throws ModelException {
if (!exists())
throw newNotPresentException();
return getParent().getUnderlyingResource();
}
/**
* @see IParent
*/
@Override
public boolean hasChildren() throws ModelException {
return getChildren().length > 0;
}
/**
* @see IModelElement
*/
@Override
public boolean isStructureKnown() throws ModelException {
// structure is always known inside an openable
return true;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof SourceRefElement))
return false;
return this.occurrenceCount == ((SourceRefElement) o).occurrenceCount
&& super.equals(o);
}
@Override
protected void toStringName(StringBuffer buffer) {
super.toStringName(buffer);
if (this.occurrenceCount > 1) {
buffer.append("#"); //$NON-NLS-1$
buffer.append(this.occurrenceCount);
}
}
/**
* Elements within compilation units and class files have no corresponding
* resource.
*
* @see IModelElement
*/
@Override
public IResource getCorrespondingResource() throws ModelException {
if (!exists())
throw newNotPresentException();
return null;
}
public IModelElement getHandleUpdatingCountFromMemento(
MementoTokenizer memento, WorkingCopyOwner owner) {
if (!memento.hasMoreTokens())
return this;
this.occurrenceCount = Integer.parseInt(memento.nextToken());
if (!memento.hasMoreTokens())
return this;
String token = memento.nextToken();
return getHandleFromMemento(token, memento, owner);
}
@Override
public IModelElement getHandleFromMemento(String token,
MementoTokenizer memento, WorkingCopyOwner workingCopyOwner) {
switch (token.charAt(0)) {
case JEM_COUNT:
return getHandleUpdatingCountFromMemento(memento, workingCopyOwner);
}
return this;
}
@Override
public void getHandleMemento(StringBuffer buff) {
super.getHandleMemento(buff);
if (this.occurrenceCount > 1) {
buff.append(JEM_COUNT);
buff.append(this.occurrenceCount);
}
}
@Override
public ISourceModule getSourceModule() {
return ((ModelElement) getParent()).getSourceModule();
}
/**
* @see ISourceReference
*/
@Override
public String getSource() throws ModelException {
IOpenable openable = getOpenableParent();
IBuffer buffer = openable.getBuffer();
ISourceRange range = getSourceRange();
int offset = range.getOffset();
int length = range.getLength();
if (offset == -1 || length == 0) {
return null;
}
int bufLen = -1;
String content = null;
if (buffer != null) {
bufLen = buffer.getLength();
} else {
if (openable instanceof ISourceModule) {
content = ((ISourceModule) openable).getSource();
if (content == null) {
return null;
}
bufLen = content.length();
} else {
return null;
}
}
if (bufLen < offset + length)
length--;
try {
if (buffer != null) {
return buffer.getText(offset, length);
} else {
return content.substring(offset, offset + length);
}
} catch (RuntimeException e) {
return null;
}
}
}