/******************************************************************************* * Copyright (c) 2005, 2017 IBM Corporation 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 * *******************************************************************************/ package org.eclipse.dltk.internal.core; import java.util.ArrayList; import org.eclipse.dltk.compiler.CharOperation; import org.eclipse.dltk.core.IMember; import org.eclipse.dltk.core.IMethod; import org.eclipse.dltk.core.IModelElement; import org.eclipse.dltk.core.INamespace; import org.eclipse.dltk.core.ISourceRange; import org.eclipse.dltk.core.IType; import org.eclipse.dltk.core.ModelException; import org.eclipse.dltk.core.SourceRange; import org.eclipse.dltk.core.WorkingCopyOwner; import org.eclipse.dltk.internal.core.util.MementoTokenizer; public abstract class Member extends SourceRefElement implements IMember { protected Member(ModelElement parent) throws IllegalArgumentException { super(parent); } @Override protected void closing(Object info) throws ModelException { } /** * @see IMember */ @Override public ISourceRange getNameRange() throws ModelException { Object elementInfo = getElementInfo(); if (elementInfo instanceof MemberElementInfo) { MemberElementInfo info = (MemberElementInfo) elementInfo; return new SourceRange(info.getNameSourceStart(), info.getNameSourceEnd() - info.getNameSourceStart() + 1); } else { return null; } } @Override public int getFlags() throws ModelException { Object o = getElementInfo(); if (o instanceof MemberElementInfo) { MemberElementInfo info = (MemberElementInfo) o; return info.getModifiers(); } else { return 0; } } @Override public INamespace getNamespace() throws ModelException { return ((MemberElementInfo) getElementInfo()).getNamespace(); } @Override public IModelElement 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; } ModelElement type = (ModelElement) 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); // case JEM_TYPE_PARAMETER: // if (!memento.hasMoreTokens()) return this; // String typeParameterName = memento.nextToken(); // ModelElement typeParameter = new TypeParameter(this, // typeParameterName); // return typeParameter.getHandleFromMemento(memento, // workingCopyOwner); } return null; } @Override public IType getType(String typeName, int count) { if (false) {// isBinary()) { throw new IllegalArgumentException( "Not a source member " + toStringWithAncestors()); //$NON-NLS-1$ } else { SourceType type = new SourceType(this, typeName); type.occurrenceCount = count; return type; } } /** * @see IMember */ @Override public IType getDeclaringType() { ModelElement parentElement = (ModelElement) getParent(); if (parentElement.getElementType() == TYPE) { return (IType) parentElement; } return null; } /* * Helper method for SourceType.findMethods and BinaryType.findMethods */ public static IMethod[] findMethods(IMethod method, IMethod[] methods) { String elementName = method.getElementName(); String[] parameters; try { parameters = method.getParameterNames(); } catch (ModelException e) { parameters = CharOperation.NO_STRINGS; e.printStackTrace(); } ArrayList<IMethod> list = new ArrayList<>(); for (int i = 0, length = methods.length; i < length; i++) { IMethod existingMethod = methods[i]; try { if (areSimilarMethods(elementName, parameters, existingMethod.getElementName(), existingMethod.getParameterNames())) { list.add(existingMethod); } } catch (ModelException e) { e.printStackTrace(); } } int size = list.size(); if (size == 0) { return null; } else { return list.toArray(new IMethod[size]); } } protected static boolean areSimilarMethods(String name1, String[] params1, String name2, String[] params2) { if (name1.equals(name2)) { int params1Length = params1.length; if (params1Length == params2.length) { for (int i = 0; i < params1Length; i++) { String simpleName1 = params1[i]; String simpleName2 = params2[i]; if (!simpleName1.equals(simpleName2)) { return false; } } return true; } } return false; } /* * 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() { IModelElement current = this; Member lastLocalContext = null; parentLoop: while (true) { switch (current.getElementType()) { case SOURCE_MODULE: break parentLoop; // done recursing case TYPE: // cannot be a local context break; case FIELD: case METHOD: // these elements can define local members lastLocalContext = (Member) current; break; } current = current.getParent(); } return lastLocalContext; } }