/*******************************************************************************
* Copyright (c) 2000, 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.rubypeople.rdt.internal.core;
import org.rubypeople.rdt.core.IMember;
import org.rubypeople.rdt.core.IRubyElement;
import org.rubypeople.rdt.core.ISourceRange;
import org.rubypeople.rdt.core.IType;
import org.rubypeople.rdt.core.RubyModelException;
import org.rubypeople.rdt.core.WorkingCopyOwner;
import org.rubypeople.rdt.internal.core.util.MementoTokenizer;
/**
* @see IMember
*/
public abstract class Member extends SourceRefElement implements IMember {
protected Member(RubyElement parent) {
super(parent);
}
protected static boolean areSimilarMethods(String name1, String[] params1, String name2, String[] params2, String[] simpleNames1) {
if (name1.equals(name2)) {
int params1Length = params1.length;
if (params1Length == params2.length) {
// TODO Check param types?
return true;
}
}
return false;
}
/**
* @see IMember
*/
public IType getDeclaringType() {
RubyElement parentElement = (RubyElement) getParent();
if (parentElement.getElementType() == TYPE) { return (IType) parentElement; }
return null;
}
/*
* Returns the outermost context defining a local element. Per construction,
* it can only be a method/field/initializarer member; thus, returns null if
* this member is already a top-level type or member type. e.g for
* X.java/X/Y/foo()/Z/bar()/T, it will return X.java/X/Y/foo()
*/
public Member getOuterMostLocalContext() {
IRubyElement current = this;
Member lastLocalContext = null;
parentLoop: while (true) {
switch (current.getElementType()) {
case SCRIPT:
break parentLoop; // done recursing
case TYPE:
// cannot be a local context
break;
case CLASS_VAR:
case INSTANCE_VAR:
case METHOD:
// these elements can define local members
lastLocalContext = (Member) current;
break;
}
current = current.getParent();
}
return lastLocalContext;
}
/**
* @see IMember
*/
public ISourceRange getNameRange() throws RubyModelException {
MemberElementInfo info = (MemberElementInfo) getElementInfo();
return new SourceRange(info.getNameSourceStart(), info.getNameSourceEnd() - info.getNameSourceStart() + 1);
}
/**
* @see IMember
*/
public IType getType(String typeName, int count) {
RubyType type = new RubyType(this, typeName);
type.occurrenceCount = count;
return type;
}
/**
*/
public String readableName() {
IRubyElement declaringType = getDeclaringType();
if (declaringType != null) {
String declaringName = ((RubyElement) getDeclaringType()).readableName();
StringBuffer buffer = new StringBuffer(declaringName);
buffer.append("::");
buffer.append(this.getElementName());
return buffer.toString();
}
return super.readableName();
}
/**
* Updates the name range for this element.
*/
protected void updateNameRange(int nameStart, int nameEnd) {
try {
MemberElementInfo info = (MemberElementInfo) getElementInfo();
info.setNameSourceStart(nameStart);
info.setNameSourceEnd(nameEnd);
} catch (RubyModelException npe) {
return;
}
}
/*
* @see RubyElement
*/
public IRubyElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner workingCopyOwner) {
switch (token.charAt(0)) {
case JEM_COUNT:
return getHandleUpdatingCountFromMemento(memento, workingCopyOwner);
case JEM_TYPE:
String typeName;
if (memento.hasMoreTokens()) {
typeName = memento.nextToken();
char firstChar = typeName.charAt(0);
if (firstChar == JEM_FIELD || firstChar == JEM_METHOD || firstChar == JEM_TYPE || firstChar == JEM_COUNT) {
token = typeName;
typeName = ""; //$NON-NLS-1$
} else {
token = null;
}
} else {
typeName = ""; //$NON-NLS-1$
token = null;
}
RubyElement type = (RubyElement)getType(typeName, 1);
if (token == null) {
return type.getHandleFromMemento(memento, workingCopyOwner);
} else {
return type.getHandleFromMemento(token, memento, workingCopyOwner);
}
// case JEM_LOCALVARIABLE:
// if (!memento.hasMoreTokens()) return this;
// String varName = memento.nextToken();
// if (!memento.hasMoreTokens()) return this;
// memento.nextToken(); // JEM_COUNT
// if (!memento.hasMoreTokens()) return this;
// int declarationStart = Integer.parseInt(memento.nextToken());
// if (!memento.hasMoreTokens()) return this;
// memento.nextToken(); // JEM_COUNT
// if (!memento.hasMoreTokens()) return this;
// int declarationEnd = Integer.parseInt(memento.nextToken());
// if (!memento.hasMoreTokens()) return this;
// memento.nextToken(); // JEM_COUNT
// if (!memento.hasMoreTokens()) return this;
// int nameStart = Integer.parseInt(memento.nextToken());
// if (!memento.hasMoreTokens()) return this;
// memento.nextToken(); // JEM_COUNT
// if (!memento.hasMoreTokens()) return this;
// int nameEnd = Integer.parseInt(memento.nextToken());
// if (!memento.hasMoreTokens()) return this;
// memento.nextToken(); // JEM_COUNT
// if (!memento.hasMoreTokens()) return this;
// String typeSignature = memento.nextToken();
// return new LocalVariable(this, varName, declarationStart, declarationEnd, nameStart, nameEnd, typeSignature);
}
return null;
}
/**
* @see JavaElement#getHandleMemento()
*/
protected char getHandleMementoDelimiter() {
return RubyElement.JEM_TYPE;
}
}