aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/test/java/com/google/devtools/build/lib/generatedprojecttest/util/BuildFileContentsGenerator.java
blob: 06d91a813dd23d5ddeb9fe8d26f0105e498855c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// Copyright 2015 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.devtools.build.lib.generatedprojecttest.util;

import com.google.common.base.Joiner;
import com.google.devtools.build.lib.testutil.BuildRuleBuilder;

/**
 * A generator of the contents of a Build File. It contains functions to aid in generating build
 * files for specific purposes.
 */
public final class BuildFileContentsGenerator implements FileContentsGenerator {

  /**
   * Builds a string of the file contents.
   */
  private final StringBuilder contents = new StringBuilder();

  /**
   * Boolean to track if default package visibility has been set - it may only happen once.
   */
  private boolean defaultPackageVisibilityIsSet = false;

  /**
   * Index for generated rule names, so they are all unique within a file.
   */
  private int index = 0;

  /**
   * @return a new unique rule name
   */
  public String uniqueRuleName() {
    index++;
    return "rule" + index;
  }

  /**
   * Set the default package visibility for this build file. If this function is never called, the
   * default package visibility is ['//visibility:public'].
   */
  public FileContentsGenerator setDefaultPackageVisibility(String... visibilityLabelList) {
    if (defaultPackageVisibilityIsSet) {
      throw new IllegalStateException("setDefaultPackageVisibility was called twice.");
    }
    contents.insert(0,
        "package(default_visibility = ['" + Joiner.on("', '").join(visibilityLabelList) + "'])\n");
    defaultPackageVisibilityIsSet = true;
    return this;
  }

  /**
   * Appends the rule built from the provided BuildRuleBuilder along with the other rules
   * generated in order to this rule to be able to build.
   */
  public FileContentsGenerator addRule(BuildRuleBuilder ruleBuilder) {
    contents.append(ruleBuilder.build());
    for (BuildRuleBuilder generatedRuleBuilder : ruleBuilder.getRulesToGenerate()) {
      contents.append(generatedRuleBuilder.build());
    }
    return this;
  }

  /**
   * Appends a chain of ruleClass rules, each depending on the one before it.
   *
   * @param ruleClass Name of the rule class to instantiate.
   * @param chainLength Number of rules to create in the chain.
   * @return this
   */
  public FileContentsGenerator addDependencyChainOfRule(String ruleClass, int chainLength) {
    BuildRuleBuilder previous;
    BuildRuleBuilder current = new BuildRuleBuilder(ruleClass, uniqueRuleName());
    contents.append(current.build());

    while (chainLength > 1) {
      previous = current;
      current = new BuildRuleBuilder(ruleClass, uniqueRuleName());
      if (ruleClass.equals("java_library") || ruleClass.equals("android_library")) {
        current.dependsVia("exports").on(previous);
      } else {
        current.dependsVia("deps").on(previous);
      }
      contents.append(current.build());
      chainLength--;
    }
    return this;
  }

  /**
   * Appends a chain of ruleClass rules, and one master rule which depends on all the other rules.
   *
   * @param ruleClass Name of the rule class to instantiate.
   * @param noOfDeps Number of rules to create as dependencies for the first rule.
   * @return this
   */
  public FileContentsGenerator addRuleWithDependencies(String ruleClass, int noOfDeps) {
    BuildRuleBuilder masterRule = new BuildRuleBuilder(ruleClass, uniqueRuleName());
    String dependingAttr = ruleClass.equals("android_library") ? "exports" : "deps";
    for (int i = 0; i < noOfDeps; i++) {
      BuildRuleBuilder dependentRule = new BuildRuleBuilder(ruleClass, uniqueRuleName());
      masterRule.dependsVia(dependingAttr).on(dependentRule);
      contents.append(dependentRule.build());
    }
    contents.append(masterRule.build());
    return this;
  }

  @Override
  public String getContents() {
    try {
      setDefaultPackageVisibility("//visibility:public");
    } catch (IllegalStateException e) {
      // Default Package Visibility already set, do nothing.
    }
    return contents.toString();
  }
}