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