Home | History | Annotate | Download | only in lookup
      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