Skip to content

Commit

Permalink
Migrate struct and Provider to the skylark build api
Browse files Browse the repository at this point in the history
RELNOTES: None.
PiperOrigin-RevId: 195013604
  • Loading branch information
c-parsons authored and Copybara-Service committed May 1, 2018
1 parent 6891ebb commit 56fbc99
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 79 deletions.
57 changes: 4 additions & 53 deletions src/main/java/com/google/devtools/build/lib/packages/Info.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,8 @@
import com.google.common.collect.Ordering;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
import com.google.devtools.build.lib.skylarkbuildapi.StructApi;
import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
import com.google.devtools.build.lib.syntax.ClassObject;
import com.google.devtools.build.lib.syntax.Environment;
import com.google.devtools.build.lib.syntax.EvalException;
Expand All @@ -44,16 +41,7 @@
import javax.annotation.Nullable;

/** An instance (in the Skylark sense, not Java) of a {@link Provider}. */
@SkylarkModule(
name = "struct",
category = SkylarkModuleCategory.BUILTIN,
doc =
"A generic object with fields. See the global <a href=\"globals.html#struct\"><code>struct"
+ "</code></a> function for more details."
+ "<p>Structs fields cannot be reassigned once the struct is created. Two structs are "
+ "equal if they have the same fields and if corresponding field values are equal."
)
public abstract class Info implements ClassObject, SkylarkValue, Serializable {
public abstract class Info implements ClassObject, StructApi, Serializable {

/** The {@link Provider} that describes the type of this instance. */
private final Provider provider;
Expand Down Expand Up @@ -223,26 +211,7 @@ public void repr(SkylarkPrinter printer) {
printer.append(")");
}

@SkylarkCallable(
name = "to_proto",
doc =
"Creates a text message from the struct parameter. This method only works if all "
+ "struct elements (recursively) are strings, ints, booleans, other structs or a "
+ "list of these types. Quotes and new lines in strings are escaped. "
+ "Keys are iterated in the sorted order. "
+ "Examples:<br><pre class=language-python>"
+ "struct(key=123).to_proto()\n# key: 123\n\n"
+ "struct(key=True).to_proto()\n# key: true\n\n"
+ "struct(key=[1, 2, 3]).to_proto()\n# key: 1\n# key: 2\n# key: 3\n\n"
+ "struct(key='text').to_proto()\n# key: \"text\"\n\n"
+ "struct(key=struct(inner_key='text')).to_proto()\n"
+ "# key {\n# inner_key: \"text\"\n# }\n\n"
+ "struct(key=[struct(inner_key=1), struct(inner_key=2)]).to_proto()\n"
+ "# key {\n# inner_key: 1\n# }\n# key {\n# inner_key: 2\n# }\n\n"
+ "struct(key=struct(inner_key=struct(inner_inner_key='text'))).to_proto()\n"
+ "# key {\n# inner_key {\n# inner_inner_key: \"text\"\n# }\n# }\n</pre>",
useLocation = true
)
@Override
public String toProto(Location loc) throws EvalException {
StringBuilder sb = new StringBuilder();
printProtoTextMessage(this, sb, 0, loc);
Expand Down Expand Up @@ -321,25 +290,7 @@ private static String escapeDoubleQuotesAndBackslashesAndNewlines(String string)
return TextFormat.escapeDoubleQuotesAndBackslashes(string).replace("\n", "\\n");
}

@SkylarkCallable(
name = "to_json",
doc =
"Creates a JSON string from the struct parameter. This method only works if all "
+ "struct elements (recursively) are strings, ints, booleans, other structs or a "
+ "list of these types. Quotes and new lines in strings are escaped. "
+ "Examples:<br><pre class=language-python>"
+ "struct(key=123).to_json()\n# {\"key\":123}\n\n"
+ "struct(key=True).to_json()\n# {\"key\":true}\n\n"
+ "struct(key=[1, 2, 3]).to_json()\n# {\"key\":[1,2,3]}\n\n"
+ "struct(key='text').to_json()\n# {\"key\":\"text\"}\n\n"
+ "struct(key=struct(inner_key='text')).to_json()\n"
+ "# {\"key\":{\"inner_key\":\"text\"}}\n\n"
+ "struct(key=[struct(inner_key=1), struct(inner_key=2)]).to_json()\n"
+ "# {\"key\":[{\"inner_key\":1},{\"inner_key\":2}]}\n\n"
+ "struct(key=struct(inner_key=struct(inner_inner_key='text'))).to_json()\n"
+ "# {\"key\":{\"inner_key\":{\"inner_inner_key\":\"text\"}}}\n</pre>",
useLocation = true
)
@Override
public String toJson(Location loc) throws EvalException {
StringBuilder sb = new StringBuilder();
printJson(this, sb, loc, "struct field", null);
Expand Down
28 changes: 2 additions & 26 deletions src/main/java/com/google/devtools/build/lib/packages/Provider.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@

import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
import com.google.devtools.build.lib.skylarkbuildapi.ProviderApi;
import com.google.devtools.build.lib.syntax.ClassObject;

/**
Expand All @@ -33,31 +32,8 @@
* <p>Prefer to use {@link Key} as a serializable identifier of {@link Provider}. In particular,
* {@link Key} should be used in all data structures exposed to Skyframe.
*/
@SkylarkModule(
name = "Provider",
doc =
"A constructor for simple value objects, known as provider instances."
+ "<br>"
+ "This value has a dual purpose:"
+ " <ul>"
+ " <li>It is a function that can be called to construct 'struct'-like values:"
+ "<pre class=\"language-python\">DataInfo = provider()\n"
+ "d = DataInfo(x = 2, y = 3)\n"
+ "print(d.x + d.y) # prints 5</pre>"
+ " Note: Some providers, defined internally, do not allow instance creation"
+ " </li>"
+ " <li>It is a <i>key</i> to access a provider instance on a"
+ " <a href=\"Target.html\">Target</a>"
+ "<pre class=\"language-python\">DataInfo = provider()\n"
+ "def _rule_impl(ctx)\n"
+ " ... ctx.attr.dep[DataInfo]</pre>"
+ " </li>"
+ " </ul>"
+ "Create a new <code>Provider</code> using the "
+ "<a href=\"globals.html#provider\">provider</a> function."
)
@Immutable
public interface Provider extends SkylarkValue {
public interface Provider extends ProviderApi {

/**
* Has this {@link Provider} been exported? All native providers are always exported. Skylark
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2017 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.skylarkbuildapi;

import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;

/** Interface for provider objects (constructors for {@link StructApi} objects). */
@SkylarkModule(
name = "Provider",
doc =
"A constructor for simple value objects, known as provider instances."
+ "<br>"
+ "This value has a dual purpose:"
+ " <ul>"
+ " <li>It is a function that can be called to construct 'struct'-like values:"
+ "<pre class=\"language-python\">DataInfo = provider()\n"
+ "d = DataInfo(x = 2, y = 3)\n"
+ "print(d.x + d.y) # prints 5</pre>"
+ " Note: Some providers, defined internally, do not allow instance creation"
+ " </li>"
+ " <li>It is a <i>key</i> to access a provider instance on a"
+ " <a href=\"Target.html\">Target</a>"
+ "<pre class=\"language-python\">DataInfo = provider()\n"
+ "def _rule_impl(ctx)\n"
+ " ... ctx.attr.dep[DataInfo]</pre>"
+ " </li>"
+ " </ul>"
+ "Create a new <code>Provider</code> using the "
+ "<a href=\"globals.html#provider\">provider</a> function."
)
public interface ProviderApi extends SkylarkValue {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright 2018 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.skylarkbuildapi;

import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
import com.google.devtools.build.lib.syntax.EvalException;

/** Interface for the "struct" object in the build API. */
@SkylarkModule(
name = "struct",
category = SkylarkModuleCategory.BUILTIN,
doc =
"A generic object with fields. See the global <a href=\"globals.html#struct\"><code>struct"
+ "</code></a> function for more details."
+ "<p>Structs fields cannot be reassigned once the struct is created. Two structs are "
+ "equal if they have the same fields and if corresponding field values are equal.")
public interface StructApi extends SkylarkValue {

@SkylarkCallable(
name = "to_proto",
doc =
"Creates a text message from the struct parameter. This method only works if all "
+ "struct elements (recursively) are strings, ints, booleans, other structs or a "
+ "list of these types. Quotes and new lines in strings are escaped. "
+ "Keys are iterated in the sorted order. "
+ "Examples:<br><pre class=language-python>"
+ "struct(key=123).to_proto()\n# key: 123\n\n"
+ "struct(key=True).to_proto()\n# key: true\n\n"
+ "struct(key=[1, 2, 3]).to_proto()\n# key: 1\n# key: 2\n# key: 3\n\n"
+ "struct(key='text').to_proto()\n# key: \"text\"\n\n"
+ "struct(key=struct(inner_key='text')).to_proto()\n"
+ "# key {\n# inner_key: \"text\"\n# }\n\n"
+ "struct(key=[struct(inner_key=1), struct(inner_key=2)]).to_proto()\n"
+ "# key {\n# inner_key: 1\n# }\n# key {\n# inner_key: 2\n# }\n\n"
+ "struct(key=struct(inner_key=struct(inner_inner_key='text'))).to_proto()\n"
+ "# key {\n# inner_key {\n# inner_inner_key: \"text\"\n# }\n# }\n</pre>",
useLocation = true)
public String toProto(Location loc) throws EvalException;

@SkylarkCallable(
name = "to_json",
doc =
"Creates a JSON string from the struct parameter. This method only works if all "
+ "struct elements (recursively) are strings, ints, booleans, other structs or a "
+ "list of these types. Quotes and new lines in strings are escaped. "
+ "Examples:<br><pre class=language-python>"
+ "struct(key=123).to_json()\n# {\"key\":123}\n\n"
+ "struct(key=True).to_json()\n# {\"key\":true}\n\n"
+ "struct(key=[1, 2, 3]).to_json()\n# {\"key\":[1,2,3]}\n\n"
+ "struct(key='text').to_json()\n# {\"key\":\"text\"}\n\n"
+ "struct(key=struct(inner_key='text')).to_json()\n"
+ "# {\"key\":{\"inner_key\":\"text\"}}\n\n"
+ "struct(key=[struct(inner_key=1), struct(inner_key=2)]).to_json()\n"
+ "# {\"key\":[{\"inner_key\":1},{\"inner_key\":2}]}\n\n"
+ "struct(key=struct(inner_key=struct(inner_inner_key='text'))).to_json()\n"
+ "# {\"key\":{\"inner_key\":{\"inner_inner_key\":\"text\"}}}\n</pre>",
useLocation = true)
public String toJson(Location loc) throws EvalException;
}

0 comments on commit 56fbc99

Please sign in to comment.