public BuildRule createBuildRule()

in src/com/facebook/buck/android/RobolectricTestDescription.java [149:463]


  public BuildRule createBuildRule(
      BuildRuleCreationContextWithTargetGraph context,
      BuildTarget buildTarget,
      BuildRuleParams params,
      RobolectricTestDescriptionArg args) {
    ActionGraphBuilder graphBuilder = context.getActionGraphBuilder();
    ProjectFilesystem projectFilesystem = context.getProjectFilesystem();

    if (JavaAbis.isClassAbiTarget(buildTarget)) {
      Preconditions.checkArgument(
          !buildTarget.getFlavors().contains(AndroidLibraryGraphEnhancer.DUMMY_R_DOT_JAVA_FLAVOR));
      BuildTarget testTarget = JavaAbis.getLibraryTarget(buildTarget);
      BuildRule testRule = graphBuilder.requireRule(testTarget);
      return CalculateClassAbi.of(
          buildTarget,
          graphBuilder,
          projectFilesystem,
          Objects.requireNonNull(testRule.getSourcePathToOutput()));
    }

    JavacOptions javacOptions =
        JavacOptionsFactory.create(
            defaultJavacOptions.getUnchecked(buildTarget.getTargetConfiguration()),
            buildTarget,
            graphBuilder,
            args);

    AndroidLibraryGraphEnhancer graphEnhancer =
        new AndroidLibraryGraphEnhancer(
            buildTarget,
            projectFilesystem,
            ImmutableSortedSet.copyOf(
                Iterables.concat(
                    params.getBuildDeps(), graphBuilder.getAllRules(args.getExportedDeps()))),
            javacFactory.create(graphBuilder, args, buildTarget.getTargetConfiguration()),
            javacOptions,
            DependencyMode.TRANSITIVE,
            args.isForceFinalResourceIds(),
            args.getResourceUnionPackage(),
            /* rName */ Optional.empty(),
            args.isUseOldStyleableFormat(),
            /* skipNonUnionRDotJava */ false);

    StringWithMacrosConverter macrosConverter =
        StringWithMacrosConverter.of(
            buildTarget,
            context.getCellPathResolver().getCellNameResolver(),
            graphBuilder,
            JavaTestDescription.MACRO_EXPANDERS);
    ImmutableList<Arg> vmArgs =
        ImmutableList.copyOf(Lists.transform(args.getVmArgs(), macrosConverter::convert));


    Optional<DummyRDotJava> dummyRDotJava =
        graphEnhancer.getBuildableForAndroidResources(
            graphBuilder, /* createBuildableIfEmpty */ true);
    RobolectricTestDescriptionArg testLibraryArgs = args;

    AndroidPlatformTarget androidPlatformTarget =
        toolchainProvider.getByName(
            AndroidPlatformTarget.DEFAULT_NAME,
            buildTarget.getTargetConfiguration(),
            AndroidPlatformTarget.class);

    Optional<UnitTestOptions> unitTestOptions = Optional.empty();
    if (dummyRDotJava.isPresent()) {
      DummyRDotJava actualDummyRDotJava = dummyRDotJava.get();
      ImmutableSortedSet<BuildRule> newDeclaredDeps =
          ImmutableSortedSet.<BuildRule>naturalOrder()
              .addAll(params.getDeclaredDeps().get())
              .add(actualDummyRDotJava)
              .build();
      if (!args.isUseBinaryResources()) {
        params = params.withDeclaredDeps(newDeclaredDeps);
        testLibraryArgs =
            testLibraryArgs.withDeps(
                Iterables.concat(
                    args.getDeps(),
                    Collections.singletonList(actualDummyRDotJava.getBuildTarget())));
      } else {
        Optional<SourcePath> maybeRoboManifest = args.getRobolectricManifest();
        Preconditions.checkArgument(
            maybeRoboManifest.isPresent(),
            "You must specify a manifest to use binary resources mode.");
        SourcePath robolectricManifest = maybeRoboManifest.get();

        FilteredResourcesProvider resourcesProvider =
            new IdentityResourcesProvider(
                actualDummyRDotJava.getAndroidResourceDeps().stream()
                    .map(HasAndroidResourceDeps::getRes)
                    .collect(ImmutableList.toImmutableList()));

        ToolProvider aapt2ToolProvider = androidPlatformTarget.getAapt2ToolProvider();

        ImmutableList<Aapt2Compile> compileables =
            AndroidBinaryResourcesGraphEnhancer.createAapt2CompileablesForResourceProvider(
                projectFilesystem,
                graphBuilder,
                aapt2ToolProvider,
                resourcesProvider,
                buildTarget,
                true,
                false);

        BuildTarget aapt2LinkBuildTarget =
            buildTarget.withAppendedFlavors(InternalFlavor.of("aapt2_link"));
        Aapt2Link aapt2Link =
            new Aapt2Link(
                aapt2LinkBuildTarget,
                projectFilesystem,
                graphBuilder,
                compileables,
                robolectricManifest,
                ManifestEntries.builder().build(),
                0,
                ImmutableList.of(),
                false,
                false,
                false,
                false,
                false,
                false,
                aapt2ToolProvider.resolve(
                    graphBuilder, aapt2LinkBuildTarget.getTargetConfiguration()),
                ImmutableList.of(),
                androidPlatformTarget.getAndroidJar(),
                false,
                ImmutableSet.of(),
                ImmutableSet.of());

        graphBuilder.addToIndex(aapt2Link);
        AaptOutputInfo aaptOutputInfo = aapt2Link.getAaptOutputInfo();

        unitTestOptions =
            Optional.of(
                new UnitTestOptions(
                    buildTarget.withAppendedFlavors(InternalFlavor.of("unit_test_options")),
                    projectFilesystem,
                    graphBuilder,
                    ImmutableMap.of(
                        "android_resource_apk",
                        graphBuilder
                            .getSourcePathResolver()
                            .getAbsolutePath(aaptOutputInfo.getPrimaryResourcesApkPath())
                            .toString())));

        graphBuilder.addToIndex(unitTestOptions.get());

        GenerateRDotJava generateRDotJava =
            new GenerateRDotJava(
                buildTarget.withAppendedFlavors(InternalFlavor.of("generate_rdot_java")),
                projectFilesystem,
                graphBuilder,
                EnumSet.noneOf(RDotTxtEntry.RType.class),
                Optional.empty(),
                ImmutableList.of(aaptOutputInfo.getPathToRDotTxt()),
                args.getResourceUnionPackage(),
                actualDummyRDotJava.getAndroidResourceDeps().stream()
                    .map(HasAndroidResourceDeps::getBuildTarget)
                    .map(graphBuilder::requireRule)
                    .collect(ImmutableSortedSet.toImmutableSortedSet(Comparator.naturalOrder())),
                ImmutableList.of(resourcesProvider));

        graphBuilder.addToIndex(generateRDotJava);

        params =
            params.copyAppendingExtraDeps(
                ImmutableSortedSet.of(generateRDotJava, unitTestOptions.get()));

        ImmutableSortedSet<SourcePath> updatedSrcs =
            ImmutableSortedSet.<SourcePath>naturalOrder()
                .addAll(testLibraryArgs.getSrcs())
                .add(generateRDotJava.getSourcePathToRZip())
                .build();

        testLibraryArgs = testLibraryArgs.withSrcs(updatedSrcs);
      }
    }

    JavaTestDescription.CxxLibraryEnhancement cxxLibraryEnhancement =
        new JavaTestDescription.CxxLibraryEnhancement(
            buildTarget,
            projectFilesystem,
            params,
            args.getUseCxxLibraries(),
            args.getCxxLibraryWhitelist(),
            graphBuilder,
            getCxxPlatform(args, buildTarget.getTargetConfiguration())
                .resolve(graphBuilder, buildTarget.getTargetConfiguration()));
    params = cxxLibraryEnhancement.updatedParams;

    BuildTarget testLibraryBuildTarget =
        buildTarget.withAppendedFlavors(JavaTest.COMPILED_TESTS_LIBRARY_FLAVOR);

    JavaLibrary testsLibrary =
        graphBuilder.addToIndex(
            DefaultJavaLibrary.rulesBuilder(
                    testLibraryBuildTarget,
                    projectFilesystem,
                    context.getToolchainProvider(),
                    params,
                    graphBuilder,
                    compilerFactory.getCompiler(
                        args.getLanguage().orElse(AndroidLibraryDescription.JvmLanguage.JAVA),
                        javacFactory,
                        buildTarget.getTargetConfiguration()),
                    javaBuckConfig,
                    testLibraryArgs)
                .setJavacOptions(javacOptions)
                .build()
                .buildLibrary());
    params = params.copyAppendingExtraDeps(ImmutableSortedSet.of(testsLibrary));

    Optional<BuildTarget> runner = args.getRunner();
    Optional<TestRunnerSpec> runnerSpecs = args.getSpecs();
    if (runnerSpecs.isPresent()) {
      JavaTestRunner testRunner;
      if (runner.isPresent()) {
        BuildRule runnerRule = graphBuilder.requireRule(runner.get());
        if (!(runnerRule instanceof JavaTestRunner)) {
          throw new HumanReadableException(
              "Robolectric tests should have a java_test_runner as the runner for test protocol");
        }
        testRunner = (JavaTestRunner) runnerRule;

      } else {
        throw new HumanReadableException(
            "Robolectric test should have a java_test_runner as the runner for test protocol");
      }

      params = params.copyAppendingExtraDeps(testRunner.getCompiledTestsLibrary());

      // Construct the build rule to build the binary JAR.
      ImmutableSet<JavaLibrary> transitiveClasspathDeps =
          JavaLibraryClasspathProvider.getClasspathDeps(params.getBuildDeps());
      ImmutableSet<SourcePath> transitiveClasspaths =
          JavaLibraryClasspathProvider.getClasspathsFromLibraries(transitiveClasspathDeps);
      JavaBinary javaBinary =
          new JavaBinary(
              buildTarget.withFlavors(InternalFlavor.of("bin")),
              projectFilesystem,
              params.copyAppendingExtraDeps(transitiveClasspathDeps),
              javaOptionsForTests
                  .apply(buildTarget.getTargetConfiguration())
                  .getJavaRuntimeLauncher(graphBuilder, buildTarget.getTargetConfiguration()),
              testRunner.getMainClass(),
              args.getManifestFile().orElse(null),
              true,
              false,
              null,
              ImmutableSet.of(),
              transitiveClasspathDeps,
              transitiveClasspaths,
              javaBuckConfig.shouldCacheBinaries(),
              javaBuckConfig.getDuplicatesLogLevel());

      graphBuilder.addToIndex(javaBinary);

      return new RobolectricTestX(
          buildTarget,
          projectFilesystem,
          params.copyAppendingExtraDeps(javaBinary),
          javaBinary,
          testsLibrary,
          args.getLabels(),
          args.getContacts(),
          TestRunnerSpecCoercer.coerce(args.getSpecs().get(), macrosConverter),
          vmArgs,
          dummyRDotJava,
          args.getUnbundledResourcesRoot(),
          args.getRobolectricRuntimeDependency(),
          javaBuckConfig
              .getDelegate()
              .getBooleanValue("test", "pass_robolectric_directories_in_file", false));
    } else if (runner.isPresent()) {
      throw new HumanReadableException("Should not have runner set when no specs are set");
    }

    return new RobolectricTest(
        buildTarget,
        projectFilesystem,
        params,
        androidPlatformTarget,
        testsLibrary,
        args.getLabels(),
        args.getContacts(),
        TestType.JUNIT,
        javacOptions.getLanguageLevelOptions().getTargetLevel(),
        vmArgs,
        cxxLibraryEnhancement.nativeLibsEnvironment,
        args.isUseBinaryResources() ? Optional.empty() : dummyRDotJava,
        unitTestOptions,
        args.getTestRuleTimeoutMs()
            .map(Optional::of)
            .orElse(
                javaBuckConfig
                    .getDelegate()
                    .getView(TestBuckConfig.class)
                    .getDefaultTestRuleTimeoutMs()),
        args.getTestCaseTimeoutMs(),
        ImmutableMap.copyOf(Maps.transformValues(args.getEnv(), macrosConverter::convert)),
        args.getRunTestSeparately(),
        args.getForkMode(),
        args.getStdOutLogLevel(),
        args.getStdErrLogLevel(),
        args.getUnbundledResourcesRoot(),
        args.getRobolectricRuntimeDependency(),
        args.getRobolectricManifest(),
        javaBuckConfig
            .getDelegate()
            .getBooleanValue("test", "pass_robolectric_directories_in_file", false),
        javaOptionsForTests
            .apply(buildTarget.getTargetConfiguration())
            .getJavaRuntimeLauncher(graphBuilder, buildTarget.getTargetConfiguration()));
  }