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 17 package com.google.turbine.binder; 18 19 import com.google.common.collect.ImmutableList; 20 import com.google.common.collect.ImmutableMap; 21 import com.google.turbine.binder.bound.SourceTypeBoundClass; 22 import com.google.turbine.binder.bound.TypeBoundClass; 23 import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo; 24 import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo; 25 import com.google.turbine.binder.bound.TypeBoundClass.ParamInfo; 26 import com.google.turbine.binder.bound.TypeBoundClass.TyVarInfo; 27 import com.google.turbine.binder.env.Env; 28 import com.google.turbine.binder.sym.ClassSymbol; 29 import com.google.turbine.binder.sym.TyVarSymbol; 30 import com.google.turbine.diag.SourceFile; 31 import com.google.turbine.type.Type; 32 import com.google.turbine.type.Type.ClassTy; 33 import com.google.turbine.type.Type.IntersectionTy; 34 import com.google.turbine.type.Type.TyKind; 35 import com.google.turbine.types.Canonicalize; 36 import java.util.Map; 37 38 /** 39 * Canonicalizes all qualified types in a {@link SourceTypeBoundClass} using {@link Canonicalize}. 40 */ 41 public class CanonicalTypeBinder { 42 bind( ClassSymbol sym, SourceTypeBoundClass base, Env<ClassSymbol, TypeBoundClass> env)43 static SourceTypeBoundClass bind( 44 ClassSymbol sym, SourceTypeBoundClass base, Env<ClassSymbol, TypeBoundClass> env) { 45 ClassTy superClassType = null; 46 if (base.superClassType() != null && base.superClassType().tyKind() == TyKind.CLASS_TY) { 47 superClassType = 48 Canonicalize.canonicalizeClassTy( 49 base.source(), 50 base.decl().position(), 51 env, 52 base.owner(), 53 (ClassTy) base.superClassType()); 54 } 55 ImmutableList.Builder<Type> interfaceTypes = ImmutableList.builder(); 56 for (Type i : base.interfaceTypes()) { 57 if (i.tyKind() == TyKind.CLASS_TY) { 58 i = 59 Canonicalize.canonicalizeClassTy( 60 base.source(), base.decl().position(), env, base.owner(), (ClassTy) i); 61 } 62 interfaceTypes.add(i); 63 } 64 ImmutableMap<TyVarSymbol, TyVarInfo> typParamTypes = 65 typeParameters(base.source(), base.decl().position(), env, sym, base.typeParameterTypes()); 66 ImmutableList<MethodInfo> methods = 67 methods(base.source(), base.decl().position(), env, sym, base.methods()); 68 ImmutableList<FieldInfo> fields = fields(base.source(), env, sym, base.fields()); 69 return new SourceTypeBoundClass( 70 interfaceTypes.build(), 71 superClassType, 72 typParamTypes, 73 base.access(), 74 methods, 75 fields, 76 base.owner(), 77 base.kind(), 78 base.children(), 79 base.typeParameters(), 80 base.enclosingScope(), 81 base.scope(), 82 base.memberImports(), 83 base.annotationMetadata(), 84 base.annotations(), 85 base.source(), 86 base.decl()); 87 } 88 fields( SourceFile source, Env<ClassSymbol, TypeBoundClass> env, ClassSymbol sym, ImmutableList<FieldInfo> fields)89 private static ImmutableList<FieldInfo> fields( 90 SourceFile source, 91 Env<ClassSymbol, TypeBoundClass> env, 92 ClassSymbol sym, 93 ImmutableList<FieldInfo> fields) { 94 ImmutableList.Builder<FieldInfo> result = ImmutableList.builder(); 95 for (FieldInfo base : fields) { 96 result.add( 97 new FieldInfo( 98 base.sym(), 99 Canonicalize.canonicalize(source, base.decl().position(), env, sym, base.type()), 100 base.access(), 101 base.annotations(), 102 base.decl(), 103 base.value())); 104 } 105 return result.build(); 106 } 107 methods( SourceFile source, int position, Env<ClassSymbol, TypeBoundClass> env, ClassSymbol sym, ImmutableList<MethodInfo> methods)108 private static ImmutableList<MethodInfo> methods( 109 SourceFile source, 110 int position, 111 Env<ClassSymbol, TypeBoundClass> env, 112 ClassSymbol sym, 113 ImmutableList<MethodInfo> methods) { 114 ImmutableList.Builder<MethodInfo> result = ImmutableList.builder(); 115 for (MethodInfo base : methods) { 116 int pos = base.decl() != null ? base.decl().position() : position; 117 ImmutableMap<TyVarSymbol, TyVarInfo> tps = 118 typeParameters(source, pos, env, sym, base.tyParams()); 119 Type ret = Canonicalize.canonicalize(source, pos, env, sym, base.returnType()); 120 ImmutableList.Builder<ParamInfo> parameters = ImmutableList.builder(); 121 for (ParamInfo parameter : base.parameters()) { 122 parameters.add(param(source, pos, env, sym, parameter)); 123 } 124 ImmutableList<Type> exceptions = canonicalizeList(source, pos, env, sym, base.exceptions()); 125 result.add( 126 new MethodInfo( 127 base.sym(), 128 tps, 129 ret, 130 parameters.build(), 131 exceptions, 132 base.access(), 133 base.defaultValue(), 134 base.decl(), 135 base.annotations(), 136 base.receiver() != null 137 ? param(source, base.decl().position(), env, sym, base.receiver()) 138 : null)); 139 } 140 return result.build(); 141 } 142 param( SourceFile source, int position, Env<ClassSymbol, TypeBoundClass> env, ClassSymbol sym, ParamInfo base)143 private static ParamInfo param( 144 SourceFile source, 145 int position, 146 Env<ClassSymbol, TypeBoundClass> env, 147 ClassSymbol sym, 148 ParamInfo base) { 149 return new ParamInfo( 150 Canonicalize.canonicalize(source, position, env, sym, base.type()), 151 base.name(), 152 base.annotations(), 153 base.access()); 154 } 155 typeParameters( SourceFile source, int position, Env<ClassSymbol, TypeBoundClass> env, ClassSymbol sym, Map<TyVarSymbol, TyVarInfo> tps)156 private static ImmutableMap<TyVarSymbol, TyVarInfo> typeParameters( 157 SourceFile source, 158 int position, 159 Env<ClassSymbol, TypeBoundClass> env, 160 ClassSymbol sym, 161 Map<TyVarSymbol, TyVarInfo> tps) { 162 ImmutableMap.Builder<TyVarSymbol, TyVarInfo> result = ImmutableMap.builder(); 163 for (Map.Entry<TyVarSymbol, TyVarInfo> e : tps.entrySet()) { 164 TyVarInfo info = e.getValue(); 165 Type bound = Canonicalize.canonicalize(source, position, env, sym, info.bound()); 166 result.put(e.getKey(), new TyVarInfo((IntersectionTy) bound, info.annotations())); 167 } 168 return result.build(); 169 } 170 canonicalizeList( SourceFile source, int position, Env<ClassSymbol, TypeBoundClass> env, ClassSymbol sym, ImmutableList<Type> types)171 private static ImmutableList<Type> canonicalizeList( 172 SourceFile source, 173 int position, 174 Env<ClassSymbol, TypeBoundClass> env, 175 ClassSymbol sym, 176 ImmutableList<Type> types) { 177 ImmutableList.Builder<Type> result = ImmutableList.builder(); 178 for (Type type : types) { 179 result.add(Canonicalize.canonicalize(source, position, env, sym, type)); 180 } 181 return result.build(); 182 } 183 } 184