/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.devtools.j2objc.jdt; import com.google.devtools.j2objc.util.ElementUtil; import com.google.devtools.j2objc.util.TypeUtil; import java.util.ArrayList; import java.util.EnumMap; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; import javax.lang.model.type.ArrayType; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.ExecutableType; import javax.lang.model.type.NoType; import javax.lang.model.type.NullType; import javax.lang.model.type.PrimitiveType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import javax.lang.model.type.WildcardType; import javax.lang.model.util.Types; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.IVariableBinding; /** * Utility methods for types. Methods not referenced by the * translator are not implemented. */ class JdtTypes implements Types { private final Map<TypeKind, PrimitiveType> primitiveTypes = new EnumMap<>(TypeKind.class); private final Map<TypeKind, TypeElement> boxedClasses = new EnumMap<>(TypeKind.class); private final Map<TypeElement, PrimitiveType> unboxedTypes = new HashMap<>(); private final NoType voidType; private final TypeMirror objectType; JdtTypes(AST ast) { populatePrimitiveMaps(ast); objectType = BindingConverter.getType(ast.resolveWellKnownType("java.lang.Object")); voidType = (NoType) BindingConverter.getType(ast.resolveWellKnownType("void")); } private void populatePrimitiveMaps(AST ast) { resolvePrimitiveType(ast, TypeKind.BOOLEAN, "boolean", "java.lang.Boolean"); resolvePrimitiveType(ast, TypeKind.BYTE, "byte", "java.lang.Byte"); resolvePrimitiveType(ast, TypeKind.CHAR, "char", "java.lang.Character"); resolvePrimitiveType(ast, TypeKind.SHORT, "short", "java.lang.Short"); resolvePrimitiveType(ast, TypeKind.INT, "int", "java.lang.Integer"); resolvePrimitiveType(ast, TypeKind.LONG, "long", "java.lang.Long"); resolvePrimitiveType(ast, TypeKind.FLOAT, "float", "java.lang.Float"); resolvePrimitiveType(ast, TypeKind.DOUBLE, "double", "java.lang.Double"); } private void resolvePrimitiveType(AST ast, TypeKind kind, String pName, String cName) { PrimitiveType primitiveType = (PrimitiveType) BindingConverter.getType(ast.resolveWellKnownType(pName)); TypeElement classElement = BindingConverter.getTypeElement(ast.resolveWellKnownType(cName)); primitiveTypes.put(kind, primitiveType); boxedClasses.put(kind, classElement); unboxedTypes.put(classElement, primitiveType); } @Override public Element asElement(TypeMirror t) { throw new AssertionError("not implemented"); } @Override public TypeMirror asMemberOf(DeclaredType containing, Element element) { return asMemberOfInternal(containing, element); } // Static version of the above for internal use. static TypeMirror asMemberOfInternal(DeclaredType containing, Element element) { ITypeBinding c = BindingConverter.unwrapTypeMirrorIntoTypeBinding(containing); if (ElementUtil.isExecutableElement(element)) { IMethodBinding e = BindingConverter.unwrapExecutableElement((ExecutableElement) element); for (IMethodBinding m : c.getDeclaredMethods()) { if (m.isSubsignature(e)) { return BindingConverter.getType(m); } } } else if (ElementUtil.isVariable(element)) { IVariableBinding declaredVar = BindingConverter.unwrapVariableElement((VariableElement) element); for (IVariableBinding var : c.getDeclaredFields()) { if (var.getVariableDeclaration().isEqualTo(declaredVar)) { return BindingConverter.getType(var.getType()); } } } throw new IllegalArgumentException("Element: " + element + " is not a member of " + containing); } @Override public TypeElement boxedClass(PrimitiveType p) { return boxedClasses.get(p.getKind()); } @Override public TypeMirror capture(TypeMirror t) { throw new AssertionError("not implemented"); } @Override public boolean contains(TypeMirror t1, TypeMirror t2) { throw new AssertionError("not implemented"); } @Override public List<? extends TypeMirror> directSupertypes(TypeMirror t) { ITypeBinding binding = BindingConverter.unwrapTypeMirrorIntoTypeBinding(t); List<TypeMirror> mirrors = new ArrayList<>(); if (binding.getSuperclass() != null) { mirrors.add(BindingConverter.getType(binding.getSuperclass())); } else if (TypeUtil.isInterface(t)) { mirrors.add(objectType); } for (ITypeBinding b : binding.getInterfaces()) { mirrors.add(BindingConverter.getType(b)); } return mirrors; } @Override public TypeMirror erasure(TypeMirror t) { ITypeBinding binding = BindingConverter.unwrapTypeMirrorIntoTypeBinding(t); return BindingConverter.getType(binding.getErasure()); } @Override public DeclaredType getDeclaredType(DeclaredType containing, TypeElement typeElem, TypeMirror... typeArgs) { throw new AssertionError("not implemented"); } @Override public DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs) { throw new AssertionError("not implemented"); } @Override public NoType getNoType(TypeKind kind) { switch (kind) { case NONE: return BindingConverter.NO_TYPE; case VOID: return voidType; default: throw new IllegalArgumentException("Not a valid NoType kind: " + kind); } } @Override public NullType getNullType() { return new JdtNullType(); } @Override public PrimitiveType getPrimitiveType(TypeKind kind) { PrimitiveType result = primitiveTypes.get(kind); if (result == null) { throw new IllegalArgumentException("Not a primitive kind: " + kind); } return result; } @Override public WildcardType getWildcardType(TypeMirror extendsBound, TypeMirror superBound) { throw new AssertionError("not implemented"); } @Override public boolean isAssignable(TypeMirror t1, TypeMirror t2) { return BindingConverter.unwrapTypeMirrorIntoTypeBinding(t1).isAssignmentCompatible( BindingConverter.unwrapTypeMirrorIntoTypeBinding(t2)); } @Override public boolean isSameType(TypeMirror t1, TypeMirror t2) { return ((JdtTypeMirror) t1).bindingsEqual((JdtTypeMirror) t2); } @Override public boolean isSubsignature(ExecutableType m1, ExecutableType m2) { return ((IMethodBinding) BindingConverter.unwrapTypeMirrorIntoBinding(m1)).isSubsignature( ((IMethodBinding) BindingConverter.unwrapTypeMirrorIntoBinding(m2))); } @Override public boolean isSubtype(TypeMirror t1, TypeMirror t2) { return BindingConverter.unwrapTypeMirrorIntoTypeBinding(t1).isSubTypeCompatible( BindingConverter.unwrapTypeMirrorIntoTypeBinding(t2)); } @Override public PrimitiveType unboxedType(TypeMirror t) { if (t.getKind() == TypeKind.DECLARED) { TypeElement e = (TypeElement) ((DeclaredType) t).asElement(); PrimitiveType result = unboxedTypes.get(e); if (result != null) { return result; } } throw new IllegalArgumentException("No unboxing convertion for: " + t); } @Override public ArrayType getArrayType(TypeMirror componentType) { return (ArrayType) BindingConverter.getType(GeneratedTypeBinding.newArrayType( BindingConverter.unwrapTypeMirrorIntoTypeBinding(componentType))); } }