| /******************************************************************************* |
| * Copyright (c) 2015, 2016 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: |
| * Stefan Xenos (Google) - Initial implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.core.nd.java; |
| |
| import java.util.List; |
| |
| import org.eclipse.jdt.internal.core.nd.Nd; |
| import org.eclipse.jdt.internal.core.nd.NdNode; |
| import org.eclipse.jdt.internal.core.nd.db.IString; |
| import org.eclipse.jdt.internal.core.nd.field.FieldOneToMany; |
| import org.eclipse.jdt.internal.core.nd.field.FieldSearchKey; |
| import org.eclipse.jdt.internal.core.nd.field.StructDef; |
| import org.eclipse.jdt.internal.core.nd.util.CharArrayUtils; |
| |
| /** |
| * Represents the fully-qualified signature a method. Holds back-pointers to all the entities that refer to the name, |
| * along with pointers to all methods that have this fully-qualified name. Note that this isn't the class declaration |
| * itself. If there are multiple jar files containing a class of the same fully-qualified name, there may also be |
| * multiple methods with the same method ID. |
| */ |
| public class NdMethodId extends NdNode { |
| public static final FieldSearchKey<JavaIndex> METHOD_NAME; |
| public static final FieldOneToMany<NdMethod> METHODS; |
| public static final FieldOneToMany<NdType> DECLARED_TYPES; |
| |
| @SuppressWarnings("hiding") |
| public static final StructDef<NdMethodId> type; |
| |
| static { |
| type = StructDef.create(NdMethodId.class, NdNode.type); |
| METHOD_NAME = FieldSearchKey.create(type, JavaIndex.METHODS); |
| METHODS = FieldOneToMany.create(type, NdMethod.METHOD_ID, 2); |
| DECLARED_TYPES = FieldOneToMany.create(type, NdType.DECLARING_METHOD); |
| |
| type.useStandardRefCounting().done(); |
| } |
| |
| public NdMethodId(Nd nd, long address) { |
| super(nd, address); |
| } |
| |
| /** |
| * |
| * @param nd |
| * @param methodIdentifier a field descriptor for the method type followed by a "#" followed by a method selector |
| * followed by method descriptor. For example, "Lorg/eclipse/MyClass#foo()Ljava/lang/Object;V" |
| */ |
| public NdMethodId(Nd nd, char[] methodIdentifier) { |
| super(nd); |
| |
| METHOD_NAME.put(nd, this.address, methodIdentifier); |
| } |
| |
| public List<NdType> getDeclaredTypes() { |
| return DECLARED_TYPES.asList(getNd(), this.address); |
| } |
| |
| /** |
| * Returns the field descriptor for the type (without a trailing ';') followed by a # followed by the method |
| * selector followed by the method descriptor. For example, "Lorg/eclipse/MyClass#foo()Ljava/lang/Object;V" |
| */ |
| public IString getMethodName() { |
| return METHOD_NAME.get(getNd(), this.address); |
| } |
| |
| public char[] getSelector() { |
| char[] name = getMethodName().getChars(); |
| int selectorStart = CharArrayUtils.indexOf('#', name) + 1; |
| int selectorEnd = CharArrayUtils.indexOf('(', name, selectorStart, name.length); |
| if (selectorEnd == -1) { |
| selectorEnd = name.length; |
| } |
| return CharArrayUtils.subarray(name, selectorStart, selectorEnd); |
| } |
| |
| public boolean isConstructor() { |
| return org.eclipse.jdt.internal.compiler.classfmt.JavaBinaryNames.isConstructor(getSelector()); |
| } |
| |
| public char[] getMethodDescriptor() { |
| char[] name = getMethodName().getChars(); |
| int descriptorStart = CharArrayUtils.indexOf('(', name, 0, name.length); |
| return CharArrayUtils.subarray(name, descriptorStart, name.length); |
| } |
| |
| public boolean isClInit() { |
| return org.eclipse.jdt.internal.compiler.classfmt.JavaBinaryNames.isClinit(getSelector()); |
| } |
| |
| public String toString() { |
| try { |
| return new String(getSelector()); |
| } catch (RuntimeException e) { |
| // This is called most often from the debugger, so we want to return something meaningful even |
| // if the code is buggy, the database is corrupt, or we don't have a read lock. |
| return super.toString(); |
| } |
| } |
| } |