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.lookup; 18 19 import static com.google.common.collect.Iterables.getLast; 20 21 import com.google.common.base.Supplier; 22 import com.google.common.base.Suppliers; 23 import com.google.common.collect.ImmutableList; 24 import com.google.turbine.binder.sym.ClassSymbol; 25 import com.google.turbine.diag.SourceFile; 26 import com.google.turbine.tree.Tree.ImportDecl; 27 import java.util.Iterator; 28 import java.util.LinkedHashMap; 29 import java.util.Map; 30 31 /** An index for statically imported members, in particular constant variables. */ 32 public class MemberImportIndex { 33 34 /** A cache of resolved static imports, keyed by the simple name of the member. */ 35 private final Map<String, Supplier<ClassSymbol>> cache = new LinkedHashMap<>(); 36 37 private final ImmutableList<Supplier<ClassSymbol>> classes; 38 39 public MemberImportIndex( 40 SourceFile source, 41 CanonicalSymbolResolver resolve, 42 TopLevelIndex tli, 43 ImmutableList<ImportDecl> imports) { 44 ImmutableList.Builder<Supplier<ClassSymbol>> packageScopes = ImmutableList.builder(); 45 for (ImportDecl i : imports) { 46 if (!i.stat()) { 47 continue; 48 } 49 if (i.wild()) { 50 packageScopes.add( 51 Suppliers.memoize( 52 new Supplier<ClassSymbol>() { 53 @Override 54 public ClassSymbol get() { 55 LookupResult result = tli.lookup(new LookupKey(i.type())); 56 return result != null ? resolve.resolve(source, i.position(), result) : null; 57 } 58 })); 59 } else { 60 cache.put( 61 getLast(i.type()), 62 Suppliers.memoize( 63 new Supplier<ClassSymbol>() { 64 @Override 65 public ClassSymbol get() { 66 LookupResult result1 = tli.lookup(new LookupKey(i.type())); 67 if (result1 == null) { 68 return null; 69 } 70 ClassSymbol sym = (ClassSymbol) result1.sym(); 71 for (int i = 0; i < result1.remaining().size() - 1; i++) { 72 sym = resolve.resolveOne(sym, result1.remaining().get(i)); 73 } 74 return sym; 75 } 76 })); 77 } 78 } 79 this.classes = packageScopes.build(); 80 } 81 82 /** Resolves the owner of a single-member static import of the given simple name. */ 83 public ClassSymbol singleMemberImport(String simpleName) { 84 Supplier<ClassSymbol> cachedResult = cache.get(simpleName); 85 return cachedResult != null ? cachedResult.get() : null; 86 } 87 88 /** 89 * Returns an iterator over all classes whose members are on-demand imported into the current 90 * compilation unit. 91 */ 92 public Iterator<ClassSymbol> onDemandImports() { 93 return new WildcardSymbols(classes.iterator()); 94 } 95 96 private static class WildcardSymbols implements Iterator<ClassSymbol> { 97 private final Iterator<Supplier<ClassSymbol>> it; 98 99 public WildcardSymbols(Iterator<Supplier<ClassSymbol>> it) { 100 this.it = it; 101 } 102 103 @Override 104 public boolean hasNext() { 105 return it.hasNext(); 106 } 107 108 @Override 109 public ClassSymbol next() { 110 return it.next().get(); 111 } 112 113 @Override 114 public void remove() { 115 throw new UnsupportedOperationException("remove"); 116 } 117 } 118 } 119