Home | History | Annotate | Download | only in desugar
      1 // Copyright 2017 The Bazel Authors. All rights reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //    http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 package com.google.devtools.build.android.desugar;
     15 
     16 import static com.google.common.base.Preconditions.checkArgument;
     17 import static com.google.common.base.Preconditions.checkState;
     18 
     19 import com.google.common.collect.ImmutableMap;
     20 import java.util.HashMap;
     21 import java.util.List;
     22 import java.util.Map;
     23 import javax.annotation.CheckReturnValue;
     24 import javax.annotation.Nullable;
     25 
     26 /**
     27  * Opens the given list of input files and compute an index of all classes in them, to avoid
     28  * scanning all inputs over and over for each class to load. An indexed inputs can have a parent
     29  * that is firstly used when a file name is searched.
     30  */
     31 class IndexedInputs {
     32 
     33   private final ImmutableMap<String, InputFileProvider> inputFiles;
     34 
     35   /**
     36    * Parent {@link IndexedInputs} to use before to search a file name into this {@link
     37    * IndexedInputs}.
     38    */
     39   @Nullable
     40   private final IndexedInputs parent;
     41 
     42   /** Index a list of input files without a parent {@link IndexedInputs}. */
     43   public IndexedInputs(List<InputFileProvider> inputProviders) {
     44     this.parent = null;
     45     this.inputFiles = indexInputs(inputProviders);
     46   }
     47 
     48   /**
     49    * Create a new {@link IndexedInputs} with input files previously indexed and with a parent {@link
     50    * IndexedInputs}.
     51    */
     52   private IndexedInputs(
     53       ImmutableMap<String, InputFileProvider> inputFiles, IndexedInputs parentIndexedInputs) {
     54     this.parent = parentIndexedInputs;
     55     this.inputFiles = inputFiles;
     56   }
     57 
     58   /**
     59    * Create a new {@link IndexedInputs} with input files already indexed and with a parent {@link
     60    * IndexedInputs}.
     61    */
     62   @CheckReturnValue
     63   public IndexedInputs withParent(IndexedInputs parent) {
     64     checkState(this.parent == null);
     65     return new IndexedInputs(this.inputFiles, parent);
     66   }
     67 
     68   @Nullable
     69   public InputFileProvider getInputFileProvider(String filename) {
     70     checkArgument(filename.endsWith(".class"));
     71 
     72     if (parent != null) {
     73       InputFileProvider inputFileProvider = parent.getInputFileProvider(filename);
     74       if (inputFileProvider != null) {
     75         return inputFileProvider;
     76       }
     77     }
     78 
     79     return inputFiles.get(filename);
     80   }
     81 
     82   private ImmutableMap<String, InputFileProvider> indexInputs(
     83       List<InputFileProvider> inputProviders) {
     84     Map<String, InputFileProvider> indexedInputs = new HashMap<>();
     85     for (InputFileProvider inputProvider : inputProviders) {
     86       for (String relativePath : inputProvider) {
     87         if (relativePath.endsWith(".class") && !indexedInputs.containsKey(relativePath)) {
     88           indexedInputs.put(relativePath, inputProvider);
     89         }
     90       }
     91     }
     92     return ImmutableMap.copyOf(indexedInputs);
     93   }
     94 }
     95