/** * Copyright (c) 2010 Darmstadt University of Technology. * 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: * Marcel Bruch - initial API and implementation. */ package org.eclipse.recommenders.jdt; import static com.google.common.base.Optional.*; import static org.eclipse.recommenders.internal.jdt.l10n.LogMessages.*; import static org.eclipse.recommenders.utils.Logs.log; import java.util.LinkedList; import java.util.List; import org.eclipse.jdt.core.dom.IBinding; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.IPackageBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.IVariableBinding; import org.eclipse.jdt.core.dom.Name; import org.eclipse.jdt.core.dom.Type; import org.eclipse.recommenders.utils.Nullable; import org.eclipse.recommenders.utils.names.IFieldName; import org.eclipse.recommenders.utils.names.IMethodName; import org.eclipse.recommenders.utils.names.IPackageName; import org.eclipse.recommenders.utils.names.ITypeName; import org.eclipse.recommenders.utils.names.VmFieldName; import org.eclipse.recommenders.utils.names.VmMethodName; import org.eclipse.recommenders.utils.names.VmPackageName; import org.eclipse.recommenders.utils.names.VmTypeName; import com.google.common.base.Optional; public final class AstBindings { private AstBindings() { // Not meant to be instantiated } public static Optional<ITypeName> toTypeName(ITypeBinding b) { if (b == null) { return absent(); } final StringBuilder sb = new StringBuilder(); b = b.getErasure(); if (b == null) { return absent(); } if (b.isArray()) { for (int i = b.getDimensions(); i-- > 0;) { sb.append('['); } b = b.getElementType(); if (b == null) { return absent(); } } final String binaryName = b.getBinaryName(); if (binaryName == null) { return absent(); } if (b.isPrimitive()) { sb.append(binaryName); } else { sb.append('L').append(binaryName.replace('.', '/')); } try { final ITypeName res = VmTypeName.get(sb.toString()); return of(res); } catch (final Exception e) { log(ERROR_FAILED_TO_CREATE_TYPENAME, b, e); return absent(); } } public static Optional<ITypeName> toTypeName(@Nullable final Type type) { if (type == null) { return absent(); } final ITypeBinding b = type.resolveBinding(); if (b == null) { return absent(); } return toTypeName(b); } public static List<ITypeName> toTypeNames(final ITypeBinding[] interfaces) { final List<ITypeName> res = new LinkedList<>(); for (final ITypeBinding b : interfaces) { final Optional<ITypeName> opt = toTypeName(b); if (opt.isPresent()) { res.add(opt.get()); } } return res; } private static boolean needsColon(final ITypeBinding p) { if (p.isArray()) { return !p.getElementType().isPrimitive(); } return !p.isPrimitive(); } /** * Converts a method binding to its IMethodName counterpart. Note that type variables filled in by JDT are ignored, * i.e., the declaring method is used to find the IMethodName. * * @param b * the binding to resolve. * @see IMethodBinding#getMethodDeclaration() */ public static Optional<IMethodName> toMethodName(IMethodBinding b) { if (b == null) { return absent(); } IMethodBinding decl = b.getMethodDeclaration(); if (decl != null) { b = decl; } final StringBuilder sb = new StringBuilder(); final ITypeName declaringType = toTypeName(b.getDeclaringClass()).orNull(); if (declaringType == null) { return absent(); } final String methodName = b.isConstructor() ? "<init>" : b.getName(); //$NON-NLS-1$ sb.append(declaringType).append('.').append(methodName).append('('); for (final ITypeBinding param : b.getParameterTypes()) { final ITypeName paramType = toTypeName(param).orNull(); if (paramType == null) { return absent(); } sb.append(paramType); if (needsColon(param)) { sb.append(';'); } } final ITypeBinding returnType = b.getReturnType(); final ITypeName obj = toTypeName(returnType).orNull(); if (obj == null) { return absent(); } sb.append(')').append(obj); if (needsColon(returnType)) { sb.append(';'); } IMethodName ref; try { ref = VmMethodName.get(sb.toString()); } catch (final Exception e1) { log(ERROR_FAILED_TO_CREATE_METHODNAME, b, e1); return absent(); } return of(ref); } public static Optional<IVariableBinding> getVariableBinding(final Name name) { final IBinding b = name.resolveBinding(); IVariableBinding res = (IVariableBinding) (b instanceof IVariableBinding ? b : null); return fromNullable(res); } public static Optional<IFieldName> toFieldName(IVariableBinding b) { if (b == null || !b.isField()) { return absent(); } String name = b.getName(); ITypeName declared = toTypeName(b.getDeclaringClass()).orNull(); ITypeName type = toTypeName(b.getType()).orNull(); if (declared == null || type == null) { return absent(); } IFieldName res = VmFieldName.get(declared.getIdentifier() + '.' + name + ';' + type.getIdentifier()); return of(res); } public static Optional<IPackageName> toPackageName(IPackageBinding pkg) { if (pkg == null) { return absent(); } String s = pkg.getName().replace('.', '/'); return Optional.of((IPackageName) VmPackageName.get(s)); } public static Optional<IPackageName> toPackageName(ITypeBinding b) { if (b == null) { return absent(); } return toPackageName(b.getPackage()); } public static List<IPackageName> toPackageNames(final ITypeBinding[] types) { final List<IPackageName> res = new LinkedList<>(); for (final ITypeBinding b : types) { final Optional<IPackageName> opt = toPackageName(b); if (opt.isPresent()) { res.add(opt.get()); } } return res; } }