1/* 2 * Copyright 2016 Google Inc. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.google.turbine.binder; 18 19import com.google.common.collect.ImmutableList; 20import com.google.common.collect.ImmutableMap; 21import com.google.turbine.binder.bound.SourceTypeBoundClass; 22import com.google.turbine.binder.bound.TypeBoundClass; 23import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo; 24import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo; 25import com.google.turbine.binder.bound.TypeBoundClass.ParamInfo; 26import com.google.turbine.binder.bound.TypeBoundClass.TyVarInfo; 27import com.google.turbine.binder.env.Env; 28import com.google.turbine.binder.sym.ClassSymbol; 29import com.google.turbine.binder.sym.TyVarSymbol; 30import com.google.turbine.type.Type; 31import com.google.turbine.type.Type.ClassTy; 32import com.google.turbine.types.Canonicalize; 33import java.util.Map; 34 35/** 36 * Canonicalizes all qualified types in a {@link SourceTypeBoundClass} using {@link Canonicalize}. 37 */ 38public class CanonicalTypeBinder { 39 40 static SourceTypeBoundClass bind( 41 ClassSymbol sym, SourceTypeBoundClass base, Env<ClassSymbol, TypeBoundClass> env) { 42 ClassTy superClassType = null; 43 if (base.superClassType() != null) { 44 superClassType = Canonicalize.canonicalizeClassTy(env, base.owner(), base.superClassType()); 45 } 46 ImmutableList.Builder<ClassTy> interfaceTypes = ImmutableList.builder(); 47 for (ClassTy i : base.interfaceTypes()) { 48 interfaceTypes.add(Canonicalize.canonicalizeClassTy(env, base.owner(), i)); 49 } 50 ImmutableMap<TyVarSymbol, TyVarInfo> typParamTypes = 51 typeParameters(env, sym, base.typeParameterTypes()); 52 ImmutableList<MethodInfo> methods = methods(env, sym, base.methods()); 53 ImmutableList<FieldInfo> fields = fields(env, sym, base.fields()); 54 return new SourceTypeBoundClass( 55 interfaceTypes.build(), 56 superClassType, 57 typParamTypes, 58 base.access(), 59 methods, 60 fields, 61 base.owner(), 62 base.kind(), 63 base.children(), 64 base.typeParameters(), 65 base.enclosingScope(), 66 base.scope(), 67 base.memberImports(), 68 base.annotationMetadata(), 69 base.annotations(), 70 base.source()); 71 } 72 73 private static ImmutableList<FieldInfo> fields( 74 Env<ClassSymbol, TypeBoundClass> env, ClassSymbol sym, ImmutableList<FieldInfo> fields) { 75 ImmutableList.Builder<FieldInfo> result = ImmutableList.builder(); 76 for (FieldInfo base : fields) { 77 result.add( 78 new FieldInfo( 79 base.sym(), 80 Canonicalize.canonicalize(env, sym, base.type()), 81 base.access(), 82 base.annotations(), 83 base.decl(), 84 base.value())); 85 } 86 return result.build(); 87 } 88 89 private static ImmutableList<MethodInfo> methods( 90 Env<ClassSymbol, TypeBoundClass> env, ClassSymbol sym, ImmutableList<MethodInfo> methods) { 91 ImmutableList.Builder<MethodInfo> result = ImmutableList.builder(); 92 for (MethodInfo base : methods) { 93 ImmutableMap<TyVarSymbol, TyVarInfo> tps = typeParameters(env, sym, base.tyParams()); 94 Type ret = Canonicalize.canonicalize(env, sym, base.returnType()); 95 ImmutableList.Builder<ParamInfo> parameters = ImmutableList.builder(); 96 for (ParamInfo parameter : base.parameters()) { 97 parameters.add(param(env, sym, parameter)); 98 } 99 ImmutableList<Type> exceptions = canonicalizeList(env, sym, base.exceptions()); 100 result.add( 101 new MethodInfo( 102 base.sym(), 103 tps, 104 ret, 105 parameters.build(), 106 exceptions, 107 base.access(), 108 base.defaultValue(), 109 base.decl(), 110 base.annotations(), 111 base.receiver() != null ? param(env, sym, base.receiver()) : null)); 112 } 113 return result.build(); 114 } 115 116 private static ParamInfo param( 117 Env<ClassSymbol, TypeBoundClass> env, ClassSymbol sym, ParamInfo base) { 118 return new ParamInfo( 119 Canonicalize.canonicalize(env, sym, base.type()), 120 base.name(), 121 base.annotations(), 122 base.access()); 123 } 124 125 private static ImmutableMap<TyVarSymbol, TyVarInfo> typeParameters( 126 Env<ClassSymbol, TypeBoundClass> env, ClassSymbol sym, Map<TyVarSymbol, TyVarInfo> tps) { 127 ImmutableMap.Builder<TyVarSymbol, TyVarInfo> result = ImmutableMap.builder(); 128 for (Map.Entry<TyVarSymbol, TyVarInfo> e : tps.entrySet()) { 129 TyVarInfo info = e.getValue(); 130 Type superClassBound = null; 131 if (info.superClassBound() != null) { 132 superClassBound = Canonicalize.canonicalize(env, sym, info.superClassBound()); 133 } 134 ImmutableList<Type> interfaceBounds = canonicalizeList(env, sym, info.interfaceBounds()); 135 result.put(e.getKey(), new TyVarInfo(superClassBound, interfaceBounds, info.annotations())); 136 } 137 return result.build(); 138 } 139 140 private static ImmutableList<Type> canonicalizeList( 141 Env<ClassSymbol, TypeBoundClass> env, ClassSymbol sym, ImmutableList<Type> types) { 142 ImmutableList.Builder<Type> result = ImmutableList.builder(); 143 for (Type type : types) { 144 result.add(Canonicalize.canonicalize(env, sym, type)); 145 } 146 return result.build(); 147 } 148} 149