Update from Google.

--
MOE_MIGRATED_REVID=85702957
diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java
new file mode 100644
index 0000000..dfd6a92
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkAttr.java
@@ -0,0 +1,350 @@
+// Copyright 2014 Google Inc. 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.rules;
+
+import static com.google.devtools.build.lib.syntax.SkylarkFunction.castList;
+
+import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.packages.Attribute;
+import com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition;
+import com.google.devtools.build.lib.packages.Attribute.SkylarkLateBound;
+import com.google.devtools.build.lib.packages.SkylarkFileType;
+import com.google.devtools.build.lib.packages.Type;
+import com.google.devtools.build.lib.packages.Type.ConversionException;
+import com.google.devtools.build.lib.syntax.Environment;
+import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.FuncallExpression;
+import com.google.devtools.build.lib.syntax.Label;
+import com.google.devtools.build.lib.syntax.SkylarkBuiltin;
+import com.google.devtools.build.lib.syntax.SkylarkBuiltin.Param;
+import com.google.devtools.build.lib.syntax.SkylarkCallbackFunction;
+import com.google.devtools.build.lib.syntax.SkylarkEnvironment;
+import com.google.devtools.build.lib.syntax.SkylarkFunction;
+import com.google.devtools.build.lib.syntax.SkylarkList;
+import com.google.devtools.build.lib.syntax.SkylarkModule;
+import com.google.devtools.build.lib.syntax.UserDefinedFunction;
+import com.google.devtools.build.lib.util.FileTypeSet;
+
+import java.util.Map;
+
+/**
+ * A helper class to provide Attr module in Skylark.
+ */
+@SkylarkModule(name = "attr", namespace = true, onlyLoadingPhase = true,
+    doc = "Module for creating new attributes. "
+    + "They are only for use with the <code>rule</code> function.")
+public final class SkylarkAttr {
+
+  private static final String MANDATORY_DOC =
+      "set to true if users have to explicitely specify the value";
+
+  private static final String ALLOW_FILES_DOC =
+      "whether File targets are allowed. Can be True, False (default), or "
+      + "a FileType filter.";
+
+  private static final String ALLOW_RULES_DOC =
+      "which rule targets (name of the classes) are allowed."
+      + "This is deprecated (kept only for compatiblity), use providers instead.";
+
+  private static final String FLAGS_DOC =
+      "deprecated, will be removed";
+
+  private static final String DEFAULT_DOC =
+      "sets the default value of the attribute.";
+
+  private static final String CONFIGURATION_DOC =
+      "configuration of the attribute. "
+      + "For example, use DATA_CFG or HOST_CFG.";
+
+  private static final String EXECUTABLE_DOC =
+      "set to True if the labels have to be executable. Access the labels with "
+      + "ctx.executable.<attribute_name>";
+
+  private static Attribute.Builder<?> createAttribute(Type<?> type, Map<String, Object> arguments,
+      FuncallExpression ast, SkylarkEnvironment env) throws EvalException, ConversionException {
+    final Location loc = ast.getLocation();
+    // We use an empty name now so that we can set it later.
+    // This trick makes sense only in the context of Skylark (builtin rules should not use it).
+    Attribute.Builder<?> builder = Attribute.attr("", type);
+
+    Object defaultValue = arguments.get("default");
+    if (defaultValue != null) {
+      if (defaultValue instanceof UserDefinedFunction) {
+        // Late bound attribute. Non label type attributes already caused a type check error.
+        builder.value(new SkylarkLateBound(
+            new SkylarkCallbackFunction((UserDefinedFunction) defaultValue, ast, env)));
+      } else {
+        builder.defaultValue(defaultValue);
+      }
+    }
+
+    for (String flag : castList(arguments.get("flags"), String.class)) {
+      builder.setPropertyFlag(flag);
+    }
+
+    if (arguments.containsKey("mandatory") && (Boolean) arguments.get("mandatory")) {
+      builder.setPropertyFlag("MANDATORY");
+    }
+
+    if (arguments.containsKey("executable") && (Boolean) arguments.get("executable")) {
+      builder.setPropertyFlag("EXECUTABLE");
+    }
+
+    if (arguments.containsKey("single_file") && (Boolean) arguments.get("single_file")) {
+      builder.setPropertyFlag("SINGLE_ARTIFACT");
+    }
+
+    if (arguments.containsKey("allow_files")) {
+      Object fileTypesObj = arguments.get("allow_files");
+      if (fileTypesObj == Boolean.TRUE) {
+        builder.allowedFileTypes(FileTypeSet.ANY_FILE);
+      } else if (fileTypesObj == Boolean.FALSE) {
+        builder.allowedFileTypes(FileTypeSet.NO_FILE);
+      } else if (fileTypesObj instanceof SkylarkFileType) {
+        builder.allowedFileTypes(((SkylarkFileType) fileTypesObj).getFileTypeSet());
+      } else {
+        throw new EvalException(loc, "allow_files should be a boolean or a filetype object.");
+      }
+    } else if (type.equals(Type.LABEL) || type.equals(Type.LABEL_LIST)) {
+      builder.allowedFileTypes(FileTypeSet.NO_FILE);
+    }
+
+    Object ruleClassesObj = arguments.get("allow_rules");
+    if (ruleClassesObj != null) {
+      builder.allowedRuleClasses(castList(ruleClassesObj, String.class,
+              "allowed rule classes for attribute definition"));
+    }
+
+    if (arguments.containsKey("providers")) {
+      builder.mandatoryProviders(castList(arguments.get("providers"), String.class));
+    }
+
+    if (arguments.containsKey("cfg")) {
+      builder.cfg((ConfigurationTransition) arguments.get("cfg"));
+    }
+    return builder;
+  }
+
+  private static Object createAttribute(Map<String, Object> kwargs, Type<?> type,
+      FuncallExpression ast, Environment env) throws EvalException {
+    try {
+      return createAttribute(type, kwargs, ast, (SkylarkEnvironment) env);
+    } catch (ConversionException e) {
+      throw new EvalException(ast.getLocation(), e.getMessage());
+    }
+  }
+
+  @SkylarkBuiltin(name = "int", doc =
+      "Creates an attribute of type int.",
+      objectType = SkylarkAttr.class,
+      returnType = Attribute.class,
+      optionalParams = {
+      @Param(name = "default", type = Integer.class,
+          doc = DEFAULT_DOC + " If not specified, default is 0."),
+      @Param(name = "flags", type = SkylarkList.class, generic1 = String.class, doc = FLAGS_DOC),
+      @Param(name = "mandatory", type = Boolean.class, doc = MANDATORY_DOC),
+      @Param(name = "cfg", type = ConfigurationTransition.class, doc = CONFIGURATION_DOC)})
+  private static SkylarkFunction integer = new SkylarkFunction("int") {
+      @Override
+      public Object call(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
+          throws EvalException {
+        return createAttribute(kwargs, Type.INTEGER, ast, env);
+      }
+    };
+
+  @SkylarkBuiltin(name = "string", doc =
+      "Creates an attribute of type string.",
+      objectType = SkylarkAttr.class,
+      returnType = Attribute.class,
+      optionalParams = {
+      @Param(name = "default", type = String.class,
+          doc = DEFAULT_DOC + " If not specified, default is \"\"."),
+      @Param(name = "flags", type = SkylarkList.class, generic1 = String.class, doc = FLAGS_DOC),
+      @Param(name = "mandatory", type = Boolean.class, doc = MANDATORY_DOC),
+      @Param(name = "cfg", type = ConfigurationTransition.class, doc = CONFIGURATION_DOC)})
+  private static SkylarkFunction string = new SkylarkFunction("string") {
+      @Override
+      public Object call(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
+          throws EvalException {
+        return createAttribute(kwargs, Type.STRING, ast, env);
+      }
+    };
+
+  @SkylarkBuiltin(name = "label", doc =
+      "Creates an attribute of type Label. "
+      + "It is the only way to specify a dependency to another target. "
+      + "If you need a dependency that the user cannot overwrite, make the attribute "
+      + "private (starts with <code>_</code>).",
+      objectType = SkylarkAttr.class,
+      returnType = Attribute.class,
+      optionalParams = {
+      @Param(name = "default", type = Label.class, callbackEnabled = true,
+          doc = DEFAULT_DOC + " If not specified, default is None. "
+              + "Use the <code>Label</code> function to specify a default value."),
+      @Param(name = "executable", type = Boolean.class, doc = EXECUTABLE_DOC),
+      @Param(name = "flags", type = SkylarkList.class, generic1 = String.class, doc = FLAGS_DOC),
+      @Param(name = "allow_files", doc = ALLOW_FILES_DOC),
+      @Param(name = "mandatory", type = Boolean.class, doc = MANDATORY_DOC),
+      @Param(name = "providers", type = SkylarkList.class, generic1 = String.class,
+          doc = "mandatory providers every dependency has to have"),
+      @Param(name = "allow_rules", type = SkylarkList.class, generic1 = String.class,
+          doc = ALLOW_RULES_DOC),
+      @Param(name = "single_file", doc =
+            "if true, the label must correspond to a single File. "
+          + "Access it through ctx.file.<attribute_name>."),
+      @Param(name = "cfg", type = ConfigurationTransition.class, doc = CONFIGURATION_DOC)})
+  private static SkylarkFunction label = new SkylarkFunction("label") {
+      @Override
+      public Object call(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
+          throws EvalException {
+        return createAttribute(kwargs, Type.LABEL, ast, env);
+      }
+    };
+
+  @SkylarkBuiltin(name = "string_list", doc =
+      "Creates an attribute of type list of strings",
+      objectType = SkylarkAttr.class,
+      returnType = Attribute.class,
+      optionalParams = {
+      @Param(name = "default", type = SkylarkList.class, generic1 = String.class,
+          doc = DEFAULT_DOC + " If not specified, default is []."),
+      @Param(name = "flags", type = SkylarkList.class, generic1 = String.class, doc = FLAGS_DOC),
+      @Param(name = "mandatory", type = Boolean.class, doc = MANDATORY_DOC),
+      @Param(name = "cfg", type = ConfigurationTransition.class,
+          doc = CONFIGURATION_DOC)})
+  private static SkylarkFunction stringList = new SkylarkFunction("string_list") {
+      @Override
+      public Object call(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
+          throws EvalException {
+        return createAttribute(kwargs, Type.STRING_LIST, ast, env);
+      }
+    };
+
+  @SkylarkBuiltin(name = "label_list", doc =
+      "Creates an attribute of type list of labels. "
+      + "See <code>label</code> for more information.",
+      objectType = SkylarkAttr.class,
+      returnType = Attribute.class,
+      optionalParams = {
+      @Param(name = "default", type = SkylarkList.class, generic1 = Label.class,
+          callbackEnabled = true,
+          doc = DEFAULT_DOC + " If not specified, default is []. "
+              + "Use the <code>Label</code> function to specify a default value."),
+      @Param(name = "flags", type = SkylarkList.class, generic1 = String.class, doc = FLAGS_DOC),
+      @Param(name = "allow_files", doc = ALLOW_FILES_DOC),
+      @Param(name = "mandatory", type = Boolean.class, doc = MANDATORY_DOC),
+      @Param(name = "allow_rules", type = SkylarkList.class, generic1 = String.class,
+          doc = ALLOW_RULES_DOC),
+      @Param(name = "providers", type = SkylarkList.class, generic1 = String.class,
+          doc = "mandatory providers every dependency has to have"),
+      @Param(name = "cfg", type = ConfigurationTransition.class, doc = CONFIGURATION_DOC)})
+  private static SkylarkFunction labelList = new SkylarkFunction("label_list") {
+      @Override
+      public Object call(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
+          throws EvalException {
+        return createAttribute(kwargs, Type.LABEL_LIST, ast, env);
+      }
+    };
+
+  @SkylarkBuiltin(name = "bool", doc =
+      "Creates an attribute of type bool. Its default value is False.",
+      objectType = SkylarkAttr.class,
+      returnType = Attribute.class,
+      optionalParams = {
+      @Param(name = "default", type = Boolean.class, doc = DEFAULT_DOC),
+      @Param(name = "flags", type = SkylarkList.class, generic1 = String.class, doc = FLAGS_DOC),
+      @Param(name = "mandatory", type = Boolean.class, doc = MANDATORY_DOC),
+      @Param(name = "cfg", type = ConfigurationTransition.class, doc = CONFIGURATION_DOC)})
+  private static SkylarkFunction bool = new SkylarkFunction("bool") {
+      @Override
+      public Object call(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
+          throws EvalException {
+        return createAttribute(kwargs, Type.BOOLEAN, ast, env);
+      }
+    };
+
+  @SkylarkBuiltin(name = "output", doc =
+      "Creates an attribute of type output. Its default value is None. "
+      + "The user provides a file name (string) and the rule must create an action that "
+      + "generates the file.",
+      objectType = SkylarkAttr.class,
+      returnType = Attribute.class,
+      optionalParams = {
+      @Param(name = "default", type = Label.class, doc = DEFAULT_DOC),
+      @Param(name = "flags", type = SkylarkList.class, generic1 = String.class, doc = FLAGS_DOC),
+      @Param(name = "mandatory", type = Boolean.class, doc = MANDATORY_DOC),
+      @Param(name = "cfg", type = ConfigurationTransition.class, doc = CONFIGURATION_DOC)})
+  private static SkylarkFunction output = new SkylarkFunction("output") {
+      @Override
+      public Object call(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
+          throws EvalException {
+        return createAttribute(kwargs, Type.OUTPUT, ast, env);
+      }
+    };
+
+  @SkylarkBuiltin(name = "output_list", doc =
+      "Creates an attribute of type list of outputs. Its default value is []. "
+      + "See <code>output</code> above for more information.",
+      objectType = SkylarkAttr.class,
+      returnType = Attribute.class,
+      optionalParams = {
+      @Param(name = "default", type = SkylarkList.class, generic1 = Label.class, doc = DEFAULT_DOC),
+      @Param(name = "flags", type = SkylarkList.class, generic1 = String.class, doc = FLAGS_DOC),
+      @Param(name = "mandatory", type = Boolean.class, doc = MANDATORY_DOC),
+      @Param(name = "cfg", type = ConfigurationTransition.class, doc = CONFIGURATION_DOC)})
+  private static SkylarkFunction outputList = new SkylarkFunction("output_list") {
+      @Override
+      public Object call(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
+          throws EvalException {
+        return createAttribute(kwargs, Type.OUTPUT_LIST, ast, env);
+      }
+    };
+
+  @SkylarkBuiltin(name = "string_dict", doc =
+      "Creates an attribute of type dictionary, mapping from string to string. "
+      + "Its default value is {}.",
+      objectType = SkylarkAttr.class,
+      returnType = Attribute.class,
+      optionalParams = {
+      @Param(name = "default", type = Map.class, doc = DEFAULT_DOC),
+      @Param(name = "flags", type = SkylarkList.class, generic1 = String.class, doc = FLAGS_DOC),
+      @Param(name = "mandatory", type = Boolean.class, doc = MANDATORY_DOC),
+      @Param(name = "cfg", type = ConfigurationTransition.class, doc = CONFIGURATION_DOC)})
+  private static SkylarkFunction stringDict = new SkylarkFunction("string_dict") {
+      @Override
+      public Object call(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
+          throws EvalException {
+        return createAttribute(kwargs, Type.STRING_DICT, ast, env);
+      }
+    };
+
+  @SkylarkBuiltin(name = "license", doc =
+      "Creates an attribute of type license. Its default value is NO_LICENSE.",
+      // TODO(bazel-team): Implement proper license support for Skylark.
+      objectType = SkylarkAttr.class,
+      returnType = Attribute.class,
+      optionalParams = {
+      @Param(name = "default", doc = DEFAULT_DOC),
+      @Param(name = "flags", type = SkylarkList.class, generic1 = String.class, doc = FLAGS_DOC),
+      @Param(name = "mandatory", type = Boolean.class, doc = MANDATORY_DOC),
+      @Param(name = "cfg", type = ConfigurationTransition.class, doc = CONFIGURATION_DOC)})
+  private static SkylarkFunction license = new SkylarkFunction("license") {
+      @Override
+      public Object call(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
+          throws EvalException {
+        return createAttribute(kwargs, Type.LICENSE, ast, env);
+      }
+    };
+}