def _add_rule_doc(self, name, doc): """Parses the attribute documentation from the docstring. Parses the attribute documentation in the given docstring and associates the rule and attribute documentation with the corresponding rule extracted from the .bzl file. Args: name: The name of the rule. doc: The docstring extracted for the rule. """ extracted_docs = common.parse_docstring(doc) if name in self.__extracted_rules: rule = self.__extracted_rules[name] rule.doc = extracted_docs.doc rule.example_doc = extracted_docs.example_doc for attr_name, desc in extracted_docs.attr_docs.iteritems(): if attr_name in rule.attrs: rule.attrs[attr_name].doc = desc # Match the output name from the docstring with the corresponding output # template name extracted from rule() and store a mapping of output # template name to documentation. for output_name, desc in extracted_docs.output_docs.iteritems(): if output_name in rule.outputs: output_template = rule.outputs[output_name] rule.output_docs[output_template] = desc
def test_outputs(self): docstring = ( 'Documentation with outputs\n' '\n' 'Args:\n' ' name: A unique name for this rule.\n' ' visibility: The visibility of this rule.\n' '\n' 'Outputs:\n' ' %{name}.jar: A Java archive.\n' ' %{name}_deploy.jar: A Java archive suitable for deployment.\n' '\n' ' Only built if explicitly requested.\n') expected_attrs = { 'name': 'A unique name for this rule.', 'visibility': 'The visibility of this rule.' } expected_outputs = { '%{name}.jar': 'A Java archive.', '%{name}_deploy.jar': ('A Java archive suitable for deployment.\n\n' 'Only built if explicitly requested.'), } extracted_docs = common.parse_docstring(docstring) self.assertEqual('Documentation with outputs', extracted_docs.doc) self.assertDictEqual(expected_attrs, extracted_docs.attr_docs) self.assertEqual('', extracted_docs.example_doc) self.assertDictEqual(expected_outputs, extracted_docs.output_docs)
def test_example(self): docstring = ('Documentation with example\n' '\n' 'Examples:\n' ' An example of how to use this rule:\n' '\n' ' example_rule()\n' '\n' ' Note about this example.\n' '\n' 'Args:\n' ' name: A unique name for this rule.\n' ' visibility: The visibility of this rule.\n') expected_attrs = { 'name': 'A unique name for this rule.', 'visibility': 'The visibility of this rule.' } expected_example_doc = ('An example of how to use this rule:\n' '\n' ' example_rule()\n' '\n' 'Note about this example.') extracted_docs = common.parse_docstring(docstring) self.assertEqual('Documentation with example', extracted_docs.doc) self.assertDictEqual(expected_attrs, extracted_docs.attr_docs) self.assertEqual(expected_example_doc, extracted_docs.example_doc) self.assertDictEqual({}, extracted_docs.output_docs)
def test_multi_line_doc(self): docstring = ('Multi-line rule and attribute documentation.\n' '\n' 'Rule doc continued here.\n' '\n' 'Args:\n' ' name: A unique name for this rule.\n' '\n' ' Documentation for name continued here.\n' ' visibility: The visibility of this rule.\n' '\n' ' Documentation for visibility continued here.\n') expected_doc = ('Multi-line rule and attribute documentation.\n' '\n' 'Rule doc continued here.') expected_attrs = { 'name': ('A unique name for this rule.\n\n' 'Documentation for name continued here.'), 'visibility': ('The visibility of this rule.\n\n' 'Documentation for visibility continued here.') } extracted_docs = common.parse_docstring(docstring) self.assertEqual(expected_doc, extracted_docs.doc) self.assertDictEqual(expected_attrs, extracted_docs.attr_docs) self.assertEqual('', extracted_docs.example_doc) self.assertDictEqual({}, extracted_docs.output_docs)
def test_example(self): docstring = ( 'Documentation with example\n' '\n' 'Examples:\n' ' An example of how to use this rule:\n' '\n' ' example_rule()\n' '\n' ' Note about this example.\n' '\n' 'Args:\n' ' name: A unique name for this rule.\n' ' visibility: The visibility of this rule.\n') expected_attrs = { 'name': 'A unique name for this rule.', 'visibility': 'The visibility of this rule.' } expected_example_doc = ( 'An example of how to use this rule:\n' '\n' ' example_rule()\n' '\n' 'Note about this example.') extracted_docs = common.parse_docstring(docstring) self.assertEqual('Documentation with example', extracted_docs.doc) self.assertDictEqual(expected_attrs, extracted_docs.attr_docs) self.assertEqual(expected_example_doc, extracted_docs.example_doc) self.assertDictEqual({}, extracted_docs.output_docs)
def test_multi_line_doc(self): docstring = ( 'Multi-line rule and attribute documentation.\n' '\n' 'Rule doc continued here.\n' '\n' 'Args:\n' ' name: A unique name for this rule.\n' '\n' ' Documentation for name continued here.\n' ' visibility: The visibility of this rule.\n' '\n' ' Documentation for visibility continued here.\n') expected_doc = ( 'Multi-line rule and attribute documentation.\n' '\n' 'Rule doc continued here.') expected_attrs = { 'name': ('A unique name for this rule.\n\n' 'Documentation for name continued here.'), 'visibility': ('The visibility of this rule.\n\n' 'Documentation for visibility continued here.') } extracted_docs = common.parse_docstring(docstring) self.assertEqual(expected_doc, extracted_docs.doc) self.assertDictEqual(expected_attrs, extracted_docs.attr_docs) self.assertEqual('', extracted_docs.example_doc) self.assertDictEqual({}, extracted_docs.output_docs)
def test_rule_doc_only(self): docstring = 'Rule documentation only docstring.' extracted_docs = common.parse_docstring(docstring) self.assertEqual('Rule documentation only docstring.', extracted_docs.doc) self.assertDictEqual({}, extracted_docs.attr_docs) self.assertEqual('', extracted_docs.example_doc) self.assertDictEqual({}, extracted_docs.output_docs)
def _add_macro_doc(self, stmt): # The defaults array contains default values for the last arguments. # The first shift arguments are mandatory. shift = len(stmt.args.args) - len(stmt.args.defaults) rule = self.__language.rule.add() rule.name = stmt.name rule.type = build_pb2.RuleDefinition.MACRO doc = ast.get_docstring(stmt) if doc: extracted_docs = common.parse_docstring(doc) rule.documentation = extracted_docs.doc if extracted_docs.example_doc: rule.example_documentation = extracted_docs.example_doc else: extracted_docs = common.ExtractedDocs(doc="", attr_docs={}, example_doc="", output_docs={}) for i in range(len(stmt.args.args)): attr = rule.attribute.add() attr_name = stmt.args.args[i].id if hasattr( stmt.args.args[i], 'id') else stmt.args.args[i].arg attr.name = attr_name if attr_name in extracted_docs.attr_docs: attr.documentation = extracted_docs.attr_docs[attr_name] if i < shift: # The first arguments are mandatory attr.mandatory = True attr.type = build_pb2.Attribute.UNKNOWN else: node = stmt.args.defaults[i - shift] attr.mandatory = False attr.type = get_type(node) if attr.type == build_pb2.Attribute.BOOLEAN: attr.default = str(node.value) if hasattr( node, 'value') else node.id if stmt.args.kwarg: attr = rule.attribute.add() attr_name = '**' + (stmt.args.kwarg.arg if hasattr( stmt.args.kwarg, 'arg') else stmt.args.kwarg) attr.name = attr_name attr.mandatory = False attr.type = build_pb2.Attribute.UNKNOWN if attr_name in extracted_docs.attr_docs: attr.documentation = extracted_docs.attr_docs[attr_name] for template, doc in extracted_docs.output_docs.items(): output = rule.output.add() output.template = template output.documentation = doc
def test_invalid_args(self): docstring = ('Rule and attribute documentation.\n' '\n' 'Foo:\n' ' name: A unique name for this rule.\n' ' visibility: The visibility of this rule.\n') extracted_docs = common.parse_docstring(docstring) self.assertEqual(docstring.strip(), extracted_docs.doc) self.assertDictEqual({}, extracted_docs.attr_docs) self.assertEqual('', extracted_docs.example_doc) self.assertDictEqual({}, extracted_docs.output_docs)
def test_invalid_args(self): docstring = ( 'Rule and attribute documentation.\n' '\n' 'Foo:\n' ' name: A unique name for this rule.\n' ' visibility: The visibility of this rule.\n') extracted_docs = common.parse_docstring(docstring) self.assertEqual(docstring.strip(), extracted_docs.doc) self.assertDictEqual({}, extracted_docs.attr_docs) self.assertEqual('', extracted_docs.example_doc) self.assertDictEqual({}, extracted_docs.output_docs)
def _add_macro_doc(self, stmt): # The defaults array contains default values for the last arguments. # The first shift arguments are mandatory. shift = len(stmt.args.args) - len(stmt.args.defaults) rule = self.__language.rule.add() rule.name = stmt.name rule.type = build_pb2.RuleDefinition.MACRO doc = ast.get_docstring(stmt) if doc: extracted_docs = common.parse_docstring(doc) rule.documentation = extracted_docs.doc if extracted_docs.example_doc: rule.example_documentation = extracted_docs.example_doc else: extracted_docs = common.ExtractedDocs( doc="", attr_docs={}, example_doc="", output_docs={}) for i in range(len(stmt.args.args)): attr = rule.attribute.add() attr_name = stmt.args.args[i].id attr.name = attr_name if attr_name in extracted_docs.attr_docs: attr.documentation = extracted_docs.attr_docs[attr_name] if i < shift: # The first arguments are mandatory attr.mandatory = True attr.type = build_pb2.Attribute.UNKNOWN else: node = stmt.args.defaults[i - shift] attr.mandatory = False attr.type = get_type(node) if attr.type == build_pb2.Attribute.BOOLEAN: attr.default = node.id if stmt.args.kwarg: attr = rule.attribute.add() attr_name = '**' + stmt.args.kwarg attr.name = attr_name attr.mandatory = False attr.type = build_pb2.Attribute.UNKNOWN if attr_name in extracted_docs.attr_docs: attr.documentation = extracted_docs.attr_docs[attr_name] for template, doc in extracted_docs.output_docs.iteritems(): output = rule.output.add() output.template = template output.documentation = doc
def test_rule_and_attribute_doc(self): docstring = ('Rule and attribute documentation.\n' '\n' 'Args:\n' ' name: A unique name for this rule.\n' ' visibility: The visibility of this rule.\n') expected_attrs = { 'name': 'A unique name for this rule.', 'visibility': 'The visibility of this rule.' } extracted_docs = common.parse_docstring(docstring) self.assertEqual('Rule and attribute documentation.', extracted_docs.doc) self.assertDictEqual(expected_attrs, extracted_docs.attr_docs) self.assertEqual('', extracted_docs.example_doc) self.assertDictEqual({}, extracted_docs.output_docs)
def test_rule_and_attribute_doc(self): docstring = ( 'Rule and attribute documentation.\n' '\n' 'Args:\n' ' name: A unique name for this rule.\n' ' visibility: The visibility of this rule.\n') expected_attrs = { 'name': 'A unique name for this rule.', 'visibility': 'The visibility of this rule.' } extracted_docs = common.parse_docstring(docstring) self.assertEqual('Rule and attribute documentation.', extracted_docs.doc) self.assertDictEqual(expected_attrs, extracted_docs.attr_docs) self.assertEqual('', extracted_docs.example_doc) self.assertDictEqual({}, extracted_docs.output_docs)