1# Copyright 2023 The Bazel Authors. All rights reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15import io 16import re 17 18from absl.testing import absltest 19from google.protobuf import text_format 20from stardoc.proto import stardoc_output_pb2 21 22from sphinxdocs.private import proto_to_markdown 23 24_EVERYTHING_MODULE = """\ 25module_docstring: "MODULE_DOC_STRING" 26file: "@repo//pkg:foo.bzl" 27 28rule_info: { 29 rule_name: "rule_1" 30 doc_string: "RULE_1_DOC_STRING" 31 attribute: { 32 name: "rule_1_attr_1", 33 doc_string: "RULE_1_ATTR_1_DOC_STRING" 34 type: STRING 35 default_value: "RULE_1_ATTR_1_DEFAULT_VALUE" 36 } 37} 38provider_info: { 39 provider_name: "ProviderAlpha" 40 doc_string: "PROVIDER_ALPHA_DOC_STRING" 41 field_info: { 42 name: "ProviderAlpha_field_a" 43 doc_string: "PROVIDER_ALPHA_FIELD_A_DOC_STRING" 44 } 45} 46func_info: { 47 function_name: "function_1" 48 doc_string: "FUNCTION_1_DOC_STRING" 49 parameter: { 50 name: "function_1_param_a" 51 doc_string: "FUNCTION_1_PARAM_A_DOC_STRING" 52 default_value: "FUNCTION_1_PARAM_A_DEFAULT_VALUE" 53 } 54 return: { 55 doc_string: "FUNCTION_1_RETURN_DOC_STRING" 56 } 57 deprecated: { 58 doc_string: "FUNCTION_1_DEPRECATED_DOC_STRING" 59 } 60} 61aspect_info: { 62 aspect_name: "aspect_1" 63 doc_string: "ASPECT_1_DOC_STRING" 64 aspect_attribute: "aspect_1_aspect_attribute_a" 65 attribute: { 66 name: "aspect_1_attribute_a", 67 doc_string: "ASPECT_1_ATTRIBUTE_A_DOC_STRING" 68 type: INT 69 default_value: "694638" 70 } 71} 72module_extension_info: { 73 extension_name: "bzlmod_ext" 74 doc_string: "BZLMOD_EXT_DOC_STRING" 75 tag_class: { 76 tag_name: "bzlmod_ext_tag_a" 77 doc_string: "BZLMOD_EXT_TAG_A_DOC_STRING" 78 attribute: { 79 name: "bzlmod_ext_tag_a_attribute_1", 80 doc_string: "BZLMOD_EXT_TAG_A_ATTRIBUTE_1_DOC_STRING" 81 type: STRING_LIST 82 default_value: "[BZLMOD_EXT_TAG_A_ATTRIBUTE_1_DEFAULT_VALUE]" 83 } 84 } 85} 86repository_rule_info: { 87 rule_name: "repository_rule", 88 doc_string: "REPOSITORY_RULE_DOC_STRING" 89 attribute: { 90 name: "repository_rule_attribute_a", 91 doc_string: "REPOSITORY_RULE_ATTRIBUTE_A_DOC_STRING" 92 type: BOOLEAN 93 default_value: "True" 94 } 95 environ: "ENV_VAR_A" 96} 97""" 98 99 100class ProtoToMarkdownTest(absltest.TestCase): 101 def setUp(self): 102 super().setUp() 103 self.stream = io.StringIO() 104 105 def _render(self, module_text): 106 renderer = proto_to_markdown._MySTRenderer( 107 module=text_format.Parse(module_text, stardoc_output_pb2.ModuleInfo()), 108 out_stream=self.stream, 109 public_load_path="", 110 ) 111 renderer.render() 112 return self.stream.getvalue() 113 114 def test_basic_rendering_everything(self): 115 actual = self._render(_EVERYTHING_MODULE) 116 117 self.assertIn("{bzl:currentfile} //pkg:foo.bzl", actual) 118 self.assertRegex(actual, "# //pkg:foo.bzl") 119 self.assertRegex(actual, "MODULE_DOC_STRING") 120 121 self.assertRegex(actual, "{bzl:rule} rule_1.*") 122 self.assertRegex(actual, "RULE_1_DOC_STRING") 123 self.assertRegex(actual, "rule_1_attr_1") 124 self.assertRegex(actual, "RULE_1_ATTR_1_DOC_STRING") 125 self.assertRegex(actual, "RULE_1_ATTR_1_DEFAULT_VALUE") 126 127 self.assertRegex(actual, "{bzl:provider} ProviderAlpha") 128 self.assertRegex(actual, "PROVIDER_ALPHA_DOC_STRING") 129 self.assertRegex(actual, "ProviderAlpha_field_a") 130 self.assertRegex(actual, "PROVIDER_ALPHA_FIELD_A_DOC_STRING") 131 132 self.assertRegex(actual, "{bzl:function} function_1") 133 self.assertRegex(actual, "FUNCTION_1_DOC_STRING") 134 self.assertRegex(actual, "function_1_param_a") 135 self.assertRegex(actual, "FUNCTION_1_PARAM_A_DOC_STRING") 136 self.assertRegex(actual, "FUNCTION_1_PARAM_A_DEFAULT_VALUE") 137 self.assertRegex(actual, "FUNCTION_1_RETURN_DOC_STRING") 138 self.assertRegex(actual, "FUNCTION_1_DEPRECATED_DOC_STRING") 139 140 self.assertRegex(actual, "{bzl:aspect} aspect_1") 141 self.assertRegex(actual, "ASPECT_1_DOC_STRING") 142 self.assertRegex(actual, "aspect_1_aspect_attribute_a") 143 self.assertRegex(actual, "aspect_1_attribute_a") 144 self.assertRegex(actual, "ASPECT_1_ATTRIBUTE_A_DOC_STRING") 145 self.assertRegex(actual, "694638") 146 147 self.assertRegex(actual, "{bzl:module-extension} bzlmod_ext") 148 self.assertRegex(actual, "BZLMOD_EXT_DOC_STRING") 149 self.assertRegex(actual, "{bzl:tag-class} bzlmod_ext_tag_a") 150 self.assertRegex(actual, "BZLMOD_EXT_TAG_A_DOC_STRING") 151 self.assertRegex(actual, "bzlmod_ext_tag_a_attribute_1") 152 self.assertRegex(actual, "BZLMOD_EXT_TAG_A_ATTRIBUTE_1_DOC_STRING") 153 self.assertRegex(actual, "BZLMOD_EXT_TAG_A_ATTRIBUTE_1_DEFAULT_VALUE") 154 155 self.assertRegex(actual, "{bzl:repo-rule} repository_rule") 156 self.assertRegex(actual, "REPOSITORY_RULE_DOC_STRING") 157 self.assertRegex(actual, "repository_rule_attribute_a") 158 self.assertRegex(actual, "REPOSITORY_RULE_ATTRIBUTE_A_DOC_STRING") 159 self.assertRegex(actual, "repository_rule_attribute_a.*=.*True") 160 self.assertRegex(actual, "ENV_VAR_A") 161 162 def test_render_signature(self): 163 actual = self._render( 164 """\ 165file: "@repo//pkg:foo.bzl" 166func_info: { 167 function_name: "func" 168 parameter: { 169 name: "param_with_default" 170 default_value: "DEFAULT" 171 } 172 parameter: { 173 name: "param_without_default" 174 } 175 parameter: { 176 name: "param_with_function_default", 177 default_value: "<function foo from //bar:baz.bzl>" 178 } 179 parameter: { 180 name: "param_with_label_default", 181 default_value: 'Label(*, "@repo//pkg:file.bzl")' 182 } 183 parameter: { 184 name: "last_param" 185 } 186} 187 """ 188 ) 189 self.assertIn("param_with_default=DEFAULT,", actual) 190 self.assertIn("{default-value}`DEFAULT`", actual) 191 self.assertIn(":arg param_with_default:", actual) 192 self.assertIn("param_without_default,", actual) 193 self.assertIn('{default-value}`"@repo//pkg:file.bzl"`', actual) 194 self.assertIn("{default-value}`'<function foo from //bar:baz.bzl>'", actual) 195 196 197if __name__ == "__main__": 198 absltest.main() 199