• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static java.util.Objects.requireNonNull;
20 
21 import com.google.auto.value.AutoValue;
22 import com.google.common.base.Splitter;
23 import com.google.common.collect.ImmutableList;
24 import com.google.common.collect.ImmutableMap;
25 import com.google.common.collect.ImmutableSet;
26 import com.google.turbine.binder.CompUnitPreprocessor.PreprocessedCompUnit;
27 import com.google.turbine.binder.Processing.ProcessorInfo;
28 import com.google.turbine.binder.Resolve.CanonicalResolver;
29 import com.google.turbine.binder.bound.BoundClass;
30 import com.google.turbine.binder.bound.HeaderBoundClass;
31 import com.google.turbine.binder.bound.ModuleInfo;
32 import com.google.turbine.binder.bound.PackageSourceBoundClass;
33 import com.google.turbine.binder.bound.PackageSourceBoundModule;
34 import com.google.turbine.binder.bound.SourceBoundClass;
35 import com.google.turbine.binder.bound.SourceHeaderBoundClass;
36 import com.google.turbine.binder.bound.SourceModuleInfo;
37 import com.google.turbine.binder.bound.SourceTypeBoundClass;
38 import com.google.turbine.binder.bound.TypeBoundClass;
39 import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo;
40 import com.google.turbine.binder.bytecode.BytecodeBoundClass;
41 import com.google.turbine.binder.env.CompoundEnv;
42 import com.google.turbine.binder.env.Env;
43 import com.google.turbine.binder.env.LazyEnv;
44 import com.google.turbine.binder.env.SimpleEnv;
45 import com.google.turbine.binder.lookup.CanonicalSymbolResolver;
46 import com.google.turbine.binder.lookup.CompoundScope;
47 import com.google.turbine.binder.lookup.CompoundTopLevelIndex;
48 import com.google.turbine.binder.lookup.ImportIndex;
49 import com.google.turbine.binder.lookup.ImportScope;
50 import com.google.turbine.binder.lookup.MemberImportIndex;
51 import com.google.turbine.binder.lookup.Scope;
52 import com.google.turbine.binder.lookup.SimpleTopLevelIndex;
53 import com.google.turbine.binder.lookup.TopLevelIndex;
54 import com.google.turbine.binder.lookup.WildImportIndex;
55 import com.google.turbine.binder.sym.ClassSymbol;
56 import com.google.turbine.binder.sym.FieldSymbol;
57 import com.google.turbine.binder.sym.ModuleSymbol;
58 import com.google.turbine.diag.SourceFile;
59 import com.google.turbine.diag.TurbineDiagnostic;
60 import com.google.turbine.diag.TurbineError;
61 import com.google.turbine.diag.TurbineError.ErrorKind;
62 import com.google.turbine.diag.TurbineLog;
63 import com.google.turbine.model.Const;
64 import com.google.turbine.model.TurbineFlag;
65 import com.google.turbine.tree.Tree;
66 import com.google.turbine.tree.Tree.CompUnit;
67 import com.google.turbine.tree.Tree.ModDecl;
68 import com.google.turbine.type.Type;
69 import java.time.Duration;
70 import java.util.Optional;
71 import javax.annotation.processing.Processor;
72 import org.jspecify.nullness.Nullable;
73 
74 /** The entry point for analysis. */
75 public final class Binder {
76 
77   /** Binds symbols and types to the given compilation units. */
bind( ImmutableList<CompUnit> units, ClassPath classpath, ClassPath bootclasspath, Optional<String> moduleVersion)78   public static @Nullable BindingResult bind(
79       ImmutableList<CompUnit> units,
80       ClassPath classpath,
81       ClassPath bootclasspath,
82       Optional<String> moduleVersion) {
83     return bind(units, classpath, Processing.ProcessorInfo.empty(), bootclasspath, moduleVersion);
84   }
85 
86   /** Binds symbols and types to the given compilation units. */
bind( ImmutableList<CompUnit> units, ClassPath classpath, ProcessorInfo processorInfo, ClassPath bootclasspath, Optional<String> moduleVersion)87   public static @Nullable BindingResult bind(
88       ImmutableList<CompUnit> units,
89       ClassPath classpath,
90       ProcessorInfo processorInfo,
91       ClassPath bootclasspath,
92       Optional<String> moduleVersion) {
93     TurbineLog log = new TurbineLog();
94     BindingResult br;
95     try {
96       br =
97           bind(
98               log,
99               units,
100               /* generatedSources= */ ImmutableMap.of(),
101               /* generatedClasses= */ ImmutableMap.of(),
102               classpath,
103               bootclasspath,
104               moduleVersion);
105       if (!processorInfo.processors().isEmpty() && !units.isEmpty()) {
106         br =
107             Processing.process(
108                 log, units, classpath, processorInfo, bootclasspath, br, moduleVersion);
109       }
110     } catch (TurbineError turbineError) {
111       throw new TurbineError(
112           ImmutableList.<TurbineDiagnostic>builder()
113               .addAll(log.diagnostics())
114               .addAll(turbineError.diagnostics())
115               .build());
116     }
117     log.maybeThrow();
118     return br;
119   }
120 
bind( TurbineLog log, ImmutableList<CompUnit> units, ImmutableMap<String, SourceFile> generatedSources, ImmutableMap<String, byte[]> generatedClasses, ClassPath classpath, ClassPath bootclasspath, Optional<String> moduleVersion)121   static BindingResult bind(
122       TurbineLog log,
123       ImmutableList<CompUnit> units,
124       ImmutableMap<String, SourceFile> generatedSources,
125       ImmutableMap<String, byte[]> generatedClasses,
126       ClassPath classpath,
127       ClassPath bootclasspath,
128       Optional<String> moduleVersion) {
129     ImmutableList<PreprocessedCompUnit> preProcessedUnits = CompUnitPreprocessor.preprocess(units);
130 
131     SimpleEnv<ClassSymbol, SourceBoundClass> ienv = bindSourceBoundClasses(preProcessedUnits);
132 
133     ImmutableSet<ClassSymbol> syms = ienv.asMap().keySet();
134 
135     CompoundTopLevelIndex tli =
136         CompoundTopLevelIndex.of(
137             SimpleTopLevelIndex.of(ienv.asMap().keySet()),
138             bootclasspath.index(),
139             classpath.index());
140 
141     CompoundEnv<ClassSymbol, BytecodeBoundClass> classPathEnv =
142         CompoundEnv.of(classpath.env()).append(bootclasspath.env());
143 
144     CompoundEnv<ModuleSymbol, ModuleInfo> classPathModuleEnv =
145         CompoundEnv.of(classpath.moduleEnv()).append(bootclasspath.moduleEnv());
146 
147     BindPackagesResult bindPackagesResult =
148         bindPackages(log, ienv, tli, preProcessedUnits, classPathEnv);
149 
150     SimpleEnv<ClassSymbol, PackageSourceBoundClass> psenv = bindPackagesResult.classes;
151     SimpleEnv<ModuleSymbol, PackageSourceBoundModule> modules = bindPackagesResult.modules;
152 
153     Env<ClassSymbol, SourceHeaderBoundClass> henv = bindHierarchy(log, syms, psenv, classPathEnv);
154 
155     Env<ClassSymbol, SourceTypeBoundClass> tenv =
156         bindTypes(
157             log,
158             syms,
159             henv,
160             CompoundEnv.<ClassSymbol, HeaderBoundClass>of(classPathEnv).append(henv));
161 
162     tenv =
163         constants(
164             syms,
165             tenv,
166             CompoundEnv.<ClassSymbol, TypeBoundClass>of(classPathEnv).append(tenv),
167             log);
168     tenv =
169         disambiguateTypeAnnotations(
170             syms, tenv, CompoundEnv.<ClassSymbol, TypeBoundClass>of(classPathEnv).append(tenv));
171     tenv =
172         canonicalizeTypes(
173             syms, tenv, CompoundEnv.<ClassSymbol, TypeBoundClass>of(classPathEnv).append(tenv));
174 
175     ImmutableList<SourceModuleInfo> boundModules =
176         bindModules(
177             modules,
178             CompoundEnv.<ClassSymbol, TypeBoundClass>of(classPathEnv).append(tenv),
179             classPathModuleEnv,
180             moduleVersion,
181             log);
182 
183     ImmutableMap.Builder<ClassSymbol, SourceTypeBoundClass> result = ImmutableMap.builder();
184     for (ClassSymbol sym : syms) {
185       result.put(sym, tenv.getNonNull(sym));
186     }
187 
188     return new BindingResult(
189         result.buildOrThrow(),
190         boundModules,
191         classPathEnv,
192         tli,
193         generatedSources,
194         generatedClasses,
195         Statistics.empty());
196   }
197 
198   /** Records enclosing declarations of member classes, and group classes by compilation unit. */
bindSourceBoundClasses( ImmutableList<PreprocessedCompUnit> units)199   static SimpleEnv<ClassSymbol, SourceBoundClass> bindSourceBoundClasses(
200       ImmutableList<PreprocessedCompUnit> units) {
201     SimpleEnv.Builder<ClassSymbol, SourceBoundClass> envBuilder = SimpleEnv.builder();
202     for (PreprocessedCompUnit unit : units) {
203       for (SourceBoundClass type : unit.types()) {
204         SourceBoundClass prev = envBuilder.put(type.sym(), type);
205         if (prev != null) {
206           throw TurbineError.format(
207               unit.source(), type.decl().position(), ErrorKind.DUPLICATE_DECLARATION, type.sym());
208         }
209       }
210     }
211     return envBuilder.build();
212   }
213 
214   static class BindPackagesResult {
215     final SimpleEnv<ClassSymbol, PackageSourceBoundClass> classes;
216     final SimpleEnv<ModuleSymbol, PackageSourceBoundModule> modules;
217 
BindPackagesResult( SimpleEnv<ClassSymbol, PackageSourceBoundClass> classes, SimpleEnv<ModuleSymbol, PackageSourceBoundModule> modules)218     BindPackagesResult(
219         SimpleEnv<ClassSymbol, PackageSourceBoundClass> classes,
220         SimpleEnv<ModuleSymbol, PackageSourceBoundModule> modules) {
221       this.classes = classes;
222       this.modules = modules;
223     }
224   }
225 
226   /** Initializes scopes for compilation unit and package-level lookup. */
bindPackages( TurbineLog log, Env<ClassSymbol, SourceBoundClass> ienv, TopLevelIndex tli, ImmutableList<PreprocessedCompUnit> units, CompoundEnv<ClassSymbol, BytecodeBoundClass> classPathEnv)227   private static BindPackagesResult bindPackages(
228       TurbineLog log,
229       Env<ClassSymbol, SourceBoundClass> ienv,
230       TopLevelIndex tli,
231       ImmutableList<PreprocessedCompUnit> units,
232       CompoundEnv<ClassSymbol, BytecodeBoundClass> classPathEnv) {
233 
234     SimpleEnv.Builder<ClassSymbol, PackageSourceBoundClass> env = SimpleEnv.builder();
235     SimpleEnv.Builder<ModuleSymbol, PackageSourceBoundModule> modules = SimpleEnv.builder();
236     Scope javaLang = tli.lookupPackage(ImmutableList.of("java", "lang"));
237     if (javaLang == null) {
238       // TODO(cushon): add support for diagnostics without a source position, and make this one
239       // of those
240       throw new IllegalArgumentException("Could not find java.lang on bootclasspath");
241     }
242     CompoundScope topLevel = CompoundScope.base(tli.scope()).append(javaLang);
243     for (PreprocessedCompUnit unit : units) {
244       ImmutableList<String> packagename =
245           ImmutableList.copyOf(Splitter.on('/').omitEmptyStrings().split(unit.packageName()));
246       Scope packageScope = tli.lookupPackage(packagename);
247       CanonicalSymbolResolver importResolver =
248           new CanonicalResolver(
249               unit.packageName(),
250               CompoundEnv.<ClassSymbol, BoundClass>of(classPathEnv).append(ienv));
251       ImportScope importScope =
252           ImportIndex.create(log.withSource(unit.source()), importResolver, tli, unit.imports());
253       ImportScope wildImportScope = WildImportIndex.create(importResolver, tli, unit.imports());
254       MemberImportIndex memberImports =
255           new MemberImportIndex(unit.source(), importResolver, tli, unit.imports());
256       ImportScope scope = ImportScope.fromScope(topLevel).append(wildImportScope);
257       // Can be null if we're compiling a package-info.java for an empty package
258       if (packageScope != null) {
259         scope = scope.append(ImportScope.fromScope(packageScope));
260       }
261       scope = scope.append(importScope);
262       if (unit.module().isPresent()) {
263         ModDecl module = unit.module().get();
264         modules.put(
265             new ModuleSymbol(module.moduleName()),
266             new PackageSourceBoundModule(module, scope, memberImports, unit.source()));
267       }
268       for (SourceBoundClass type : unit.types()) {
269         env.put(type.sym(), new PackageSourceBoundClass(type, scope, memberImports, unit.source()));
270       }
271     }
272     return new BindPackagesResult(env.build(), modules.build());
273   }
274 
275   /** Binds the type hierarchy (superclasses and interfaces) for all classes in the compilation. */
bindHierarchy( TurbineLog log, Iterable<ClassSymbol> syms, final SimpleEnv<ClassSymbol, PackageSourceBoundClass> psenv, CompoundEnv<ClassSymbol, BytecodeBoundClass> classPathEnv)276   private static Env<ClassSymbol, SourceHeaderBoundClass> bindHierarchy(
277       TurbineLog log,
278       Iterable<ClassSymbol> syms,
279       final SimpleEnv<ClassSymbol, PackageSourceBoundClass> psenv,
280       CompoundEnv<ClassSymbol, BytecodeBoundClass> classPathEnv) {
281     ImmutableMap.Builder<
282             ClassSymbol, LazyEnv.Completer<ClassSymbol, HeaderBoundClass, SourceHeaderBoundClass>>
283         completers = ImmutableMap.builder();
284     for (ClassSymbol sym : syms) {
285       completers.put(
286           sym,
287           new LazyEnv.Completer<ClassSymbol, HeaderBoundClass, SourceHeaderBoundClass>() {
288             @Override
289             public SourceHeaderBoundClass complete(
290                 Env<ClassSymbol, HeaderBoundClass> henv, ClassSymbol sym) {
291               PackageSourceBoundClass base = psenv.getNonNull(sym);
292               return HierarchyBinder.bind(log.withSource(base.source()), sym, base, henv);
293             }
294           });
295     }
296     return new LazyEnv<>(completers.buildOrThrow(), classPathEnv);
297   }
298 
bindTypes( TurbineLog log, ImmutableSet<ClassSymbol> syms, Env<ClassSymbol, SourceHeaderBoundClass> shenv, Env<ClassSymbol, HeaderBoundClass> henv)299   private static Env<ClassSymbol, SourceTypeBoundClass> bindTypes(
300       TurbineLog log,
301       ImmutableSet<ClassSymbol> syms,
302       Env<ClassSymbol, SourceHeaderBoundClass> shenv,
303       Env<ClassSymbol, HeaderBoundClass> henv) {
304     SimpleEnv.Builder<ClassSymbol, SourceTypeBoundClass> builder = SimpleEnv.builder();
305     for (ClassSymbol sym : syms) {
306       SourceHeaderBoundClass base = shenv.getNonNull(sym);
307       builder.put(sym, TypeBinder.bind(log.withSource(base.source()), henv, sym, base));
308     }
309     return builder.build();
310   }
311 
canonicalizeTypes( ImmutableSet<ClassSymbol> syms, Env<ClassSymbol, SourceTypeBoundClass> stenv, Env<ClassSymbol, TypeBoundClass> tenv)312   private static Env<ClassSymbol, SourceTypeBoundClass> canonicalizeTypes(
313       ImmutableSet<ClassSymbol> syms,
314       Env<ClassSymbol, SourceTypeBoundClass> stenv,
315       Env<ClassSymbol, TypeBoundClass> tenv) {
316     SimpleEnv.Builder<ClassSymbol, SourceTypeBoundClass> builder = SimpleEnv.builder();
317     for (ClassSymbol sym : syms) {
318       SourceTypeBoundClass base = stenv.getNonNull(sym);
319       builder.put(sym, CanonicalTypeBinder.bind(sym, base, tenv));
320     }
321     return builder.build();
322   }
323 
bindModules( SimpleEnv<ModuleSymbol, PackageSourceBoundModule> modules, CompoundEnv<ClassSymbol, TypeBoundClass> env, CompoundEnv<ModuleSymbol, ModuleInfo> moduleEnv, Optional<String> moduleVersion, TurbineLog log)324   private static ImmutableList<SourceModuleInfo> bindModules(
325       SimpleEnv<ModuleSymbol, PackageSourceBoundModule> modules,
326       CompoundEnv<ClassSymbol, TypeBoundClass> env,
327       CompoundEnv<ModuleSymbol, ModuleInfo> moduleEnv,
328       Optional<String> moduleVersion,
329       TurbineLog log) {
330     // Allow resolution of modules in the current compilation. Currently this is only needed for
331     // version strings in requires directives.
332     moduleEnv =
333         moduleEnv.append(
334             new Env<ModuleSymbol, ModuleInfo>() {
335               @Override
336               public @Nullable ModuleInfo get(ModuleSymbol sym) {
337                 PackageSourceBoundModule info = modules.get(sym);
338                 if (info != null) {
339                   return new ModuleInfo(
340                       info.module().moduleName(),
341                       moduleVersion.orElse(null),
342                       /* flags= */ 0,
343                       /* annos= */ ImmutableList.of(),
344                       /* requires= */ ImmutableList.of(),
345                       /* exports= */ ImmutableList.of(),
346                       /* opens= */ ImmutableList.of(),
347                       /* uses= */ ImmutableList.of(),
348                       /* provides= */ ImmutableList.of());
349                 }
350                 return null;
351               }
352             });
353     ImmutableList.Builder<SourceModuleInfo> bound = ImmutableList.builder();
354     for (PackageSourceBoundModule module : modules.asMap().values()) {
355       bound.add(
356           ModuleBinder.bind(
357               module, env, moduleEnv, moduleVersion, log.withSource(module.source())));
358     }
359     return bound.build();
360   }
361 
constants( ImmutableSet<ClassSymbol> syms, Env<ClassSymbol, SourceTypeBoundClass> env, CompoundEnv<ClassSymbol, TypeBoundClass> baseEnv, TurbineLog log)362   private static Env<ClassSymbol, SourceTypeBoundClass> constants(
363       ImmutableSet<ClassSymbol> syms,
364       Env<ClassSymbol, SourceTypeBoundClass> env,
365       CompoundEnv<ClassSymbol, TypeBoundClass> baseEnv,
366       TurbineLog log) {
367 
368     // Prepare to lazily evaluate constant fields in each compilation unit.
369     // The laziness is necessary since constant fields can reference other
370     // constant fields.
371     ImmutableMap.Builder<FieldSymbol, LazyEnv.Completer<FieldSymbol, Const.Value, Const.Value>>
372         completers = ImmutableMap.builder();
373     for (ClassSymbol sym : syms) {
374       SourceTypeBoundClass info = env.getNonNull(sym);
375       for (FieldInfo field : info.fields()) {
376         if (!isConst(field)) {
377           continue;
378         }
379         completers.put(
380             field.sym(),
381             new LazyEnv.Completer<FieldSymbol, Const.Value, Const.Value>() {
382               @Override
383               public Const.@Nullable Value complete(
384                   Env<FieldSymbol, Const.Value> env1, FieldSymbol k) {
385                 try {
386                   return new ConstEvaluator(
387                           sym,
388                           sym,
389                           info.memberImports(),
390                           info.source(),
391                           info.scope(),
392                           env1,
393                           baseEnv,
394                           log.withSource(info.source()))
395                       .evalFieldInitializer(
396                           // we're processing fields bound from sources in the compilation
397                           requireNonNull(field.decl()).init().get(), field.type());
398                 } catch (LazyEnv.LazyBindingError e) {
399                   // fields initializers are allowed to reference the field being initialized,
400                   // but if they do they aren't constants
401                   return null;
402                 }
403               }
404             });
405       }
406     }
407 
408     // Create an environment of constant field values that combines
409     // lazily evaluated fields in the current compilation unit with
410     // constant fields in the classpath (which don't require evaluation).
411     Env<FieldSymbol, Const.Value> constenv =
412         new LazyEnv<>(
413             completers.buildOrThrow(), SimpleEnv.<FieldSymbol, Const.Value>builder().build());
414 
415     SimpleEnv.Builder<ClassSymbol, SourceTypeBoundClass> builder = SimpleEnv.builder();
416     for (ClassSymbol sym : syms) {
417       SourceTypeBoundClass base = env.getNonNull(sym);
418       builder.put(
419           sym, new ConstBinder(constenv, sym, baseEnv, base, log.withSource(base.source())).bind());
420     }
421     return builder.build();
422   }
423 
isConst(FieldInfo field)424   static boolean isConst(FieldInfo field) {
425     if ((field.access() & TurbineFlag.ACC_FINAL) == 0) {
426       return false;
427     }
428     if (field.decl() == null) {
429       return false;
430     }
431     final Optional<Tree.Expression> init = field.decl().init();
432     if (!init.isPresent()) {
433       return false;
434     }
435     switch (field.type().tyKind()) {
436       case PRIM_TY:
437         break;
438       case CLASS_TY:
439         if (((Type.ClassTy) field.type()).sym().equals(ClassSymbol.STRING)) {
440           break;
441         }
442         // fall through
443       default:
444         return false;
445     }
446     return true;
447   }
448 
449   /**
450    * Disambiguate annotations on field types and method return types that could be declaration or
451    * type annotations.
452    */
disambiguateTypeAnnotations( ImmutableSet<ClassSymbol> syms, Env<ClassSymbol, SourceTypeBoundClass> stenv, Env<ClassSymbol, TypeBoundClass> tenv)453   private static Env<ClassSymbol, SourceTypeBoundClass> disambiguateTypeAnnotations(
454       ImmutableSet<ClassSymbol> syms,
455       Env<ClassSymbol, SourceTypeBoundClass> stenv,
456       Env<ClassSymbol, TypeBoundClass> tenv) {
457     SimpleEnv.Builder<ClassSymbol, SourceTypeBoundClass> builder = SimpleEnv.builder();
458     for (ClassSymbol sym : syms) {
459       SourceTypeBoundClass base = stenv.getNonNull(sym);
460       builder.put(sym, DisambiguateTypeAnnotations.bind(base, tenv));
461     }
462     return builder.build();
463   }
464 
465   /** Statistics about annotation processing. */
466   @AutoValue
467   public abstract static class Statistics {
468 
469     /**
470      * The total elapsed time spent in {@link Processor#init} and {@link Processor#process} across
471      * all rounds for each annotation processor.
472      */
processingTime()473     public abstract ImmutableMap<String, Duration> processingTime();
474 
475     /**
476      * Serialized protos containing processor-specific metrics. Currently only supported for Dagger.
477      */
processorMetrics()478     public abstract ImmutableMap<String, byte[]> processorMetrics();
479 
create( ImmutableMap<String, Duration> processingTime, ImmutableMap<String, byte[]> processorMetrics)480     public static Statistics create(
481         ImmutableMap<String, Duration> processingTime,
482         ImmutableMap<String, byte[]> processorMetrics) {
483       return new AutoValue_Binder_Statistics(processingTime, processorMetrics);
484     }
485 
empty()486     public static Statistics empty() {
487       return create(ImmutableMap.of(), ImmutableMap.of());
488     }
489   }
490 
491   /** The result of binding: bound nodes for sources in the compilation, and the classpath. */
492   public static class BindingResult {
493     private final ImmutableMap<ClassSymbol, SourceTypeBoundClass> units;
494     private final ImmutableList<SourceModuleInfo> modules;
495     private final CompoundEnv<ClassSymbol, BytecodeBoundClass> classPathEnv;
496     private final TopLevelIndex tli;
497     private final ImmutableMap<String, SourceFile> generatedSources;
498     private final ImmutableMap<String, byte[]> generatedClasses;
499     private final Statistics statistics;
500 
BindingResult( ImmutableMap<ClassSymbol, SourceTypeBoundClass> units, ImmutableList<SourceModuleInfo> modules, CompoundEnv<ClassSymbol, BytecodeBoundClass> classPathEnv, TopLevelIndex tli, ImmutableMap<String, SourceFile> generatedSources, ImmutableMap<String, byte[]> generatedClasses, Statistics statistics)501     public BindingResult(
502         ImmutableMap<ClassSymbol, SourceTypeBoundClass> units,
503         ImmutableList<SourceModuleInfo> modules,
504         CompoundEnv<ClassSymbol, BytecodeBoundClass> classPathEnv,
505         TopLevelIndex tli,
506         ImmutableMap<String, SourceFile> generatedSources,
507         ImmutableMap<String, byte[]> generatedClasses,
508         Statistics statistics) {
509       this.units = units;
510       this.modules = modules;
511       this.classPathEnv = classPathEnv;
512       this.tli = tli;
513       this.generatedSources = generatedSources;
514       this.generatedClasses = generatedClasses;
515       this.statistics = statistics;
516     }
517 
518     /** Bound nodes for sources in the compilation. */
units()519     public ImmutableMap<ClassSymbol, SourceTypeBoundClass> units() {
520       return units;
521     }
522 
modules()523     public ImmutableList<SourceModuleInfo> modules() {
524       return modules;
525     }
526 
527     /** The classpath. */
classPathEnv()528     public CompoundEnv<ClassSymbol, BytecodeBoundClass> classPathEnv() {
529       return classPathEnv;
530     }
531 
tli()532     public TopLevelIndex tli() {
533       return tli;
534     }
535 
generatedSources()536     public ImmutableMap<String, SourceFile> generatedSources() {
537       return generatedSources;
538     }
539 
generatedClasses()540     public ImmutableMap<String, byte[]> generatedClasses() {
541       return generatedClasses;
542     }
543 
statistics()544     public Statistics statistics() {
545       return statistics;
546     }
547 
withGeneratedClasses(ImmutableMap<String, byte[]> generatedClasses)548     public BindingResult withGeneratedClasses(ImmutableMap<String, byte[]> generatedClasses) {
549       return new BindingResult(
550           units, modules, classPathEnv, tli, generatedSources, generatedClasses, statistics);
551     }
552 
withGeneratedSources(ImmutableMap<String, SourceFile> generatedSources)553     public BindingResult withGeneratedSources(ImmutableMap<String, SourceFile> generatedSources) {
554       return new BindingResult(
555           units, modules, classPathEnv, tli, generatedSources, generatedClasses, statistics);
556     }
557 
withStatistics(Statistics statistics)558     public BindingResult withStatistics(Statistics statistics) {
559       return new BindingResult(
560           units, modules, classPathEnv, tli, generatedSources, generatedClasses, statistics);
561     }
562   }
563 
Binder()564   private Binder() {}
565 }
566