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