| # Copyright 2016 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. |
| |
| """Representations used for rendering documentation templates.""" |
| |
| |
| # internal imports |
| import os |
| from skydoc import build_pb2 |
| |
| |
| class Attribute(object): |
| """Representation of an attribute used to render documentation templates.""" |
| |
| NAME_LINK = ( |
| '<a href="https://bazel.build/docs/build-ref.html#name">Name</a>') |
| LABEL_LINK = ( |
| '<a href="https://bazel.build/docs/build-ref.html#labels">Label</a>') |
| LABELS_LINK = ( |
| '<a href="https://bazel.build/docs/build-ref.html#labels">labels</a>') |
| |
| def __init__(self, proto): |
| self.__proto = proto |
| self.name = proto.name |
| self.type = self._get_type_str(proto) |
| if proto.name == 'name' and not proto.documentation: |
| self.documentation = 'A unique name for this rule.' |
| else: |
| self.documentation = proto.documentation |
| |
| def _get_type_str(self, proto): |
| type_str = '' |
| if proto.type == build_pb2.Attribute.INTEGER: |
| type_str = 'Integer' |
| elif proto.type == build_pb2.Attribute.STRING: |
| type_str = 'String' |
| elif proto.type == build_pb2.Attribute.LABEL: |
| type_str = self.LABEL_LINK |
| elif proto.type == build_pb2.Attribute.OUTPUT: |
| type_str = 'Output' |
| elif proto.type == build_pb2.Attribute.STRING_LIST: |
| type_str = 'List of strings' |
| elif proto.type == build_pb2.Attribute.LABEL_LIST: |
| type_str = 'List of %s' % self.LABELS_LINK |
| elif proto.type == build_pb2.Attribute.OUTPUT_LIST: |
| type_str = 'List of outputs' |
| elif proto.type == build_pb2.Attribute.DISTRIBUTION_SET: |
| type_str = 'Distribution Set' |
| elif proto.type == build_pb2.Attribute.LICENSE: |
| type_str = 'License' |
| elif proto.type == build_pb2.Attribute.STRING_DICT: |
| type_str = 'Dictionary mapping strings to string' |
| elif proto.type == build_pb2.Attribute.FILESET_ENTRY_LIST: |
| type_str = 'List of FilesetEntry' |
| elif proto.type == build_pb2.Attribute.LABEL_LIST_DICT: |
| type_str = 'Dictionary mapping strings to lists of %s' % self.LABELS_LINK |
| elif proto.type == build_pb2.Attribute.STRING_LIST_DICT: |
| type_str = 'Dictionary mapping strings to lists of strings' |
| elif proto.type == build_pb2.Attribute.BOOLEAN: |
| type_str = 'Boolean' |
| elif proto.type == build_pb2.Attribute.TRISTATE: |
| type_str = 'Tristate' |
| elif proto.type == build_pb2.Attribute.INTEGER_LIST: |
| type_str = 'List of integers' |
| elif proto.type == build_pb2.Attribute.LABEL_DICT_UNARY: |
| type_str = 'Label Dict Unary' |
| elif proto.type == build_pb2.Attribute.SELECTOR_LIST: |
| type_str = 'Selector List' |
| elif proto.type == build_pb2.Attribute.LABEL_KEYED_STRING_DICT: |
| type_str = 'Dictionary mapping %s to strings' % self.LABELS_LINK |
| else: |
| if proto.name == 'name': |
| type_str = self.NAME_LINK |
| else: |
| type_str = 'Unknown' |
| |
| type_str += '; Required' if proto.mandatory else '; Optional' |
| if proto.HasField('default') and not proto.mandatory: |
| type_str += '; Default is ' + proto.default |
| return type_str |
| |
| |
| class Output(object): |
| """Representation of an output used to render documentation templates.""" |
| |
| def __init__(self, proto): |
| self.__proto = proto |
| self.template = proto.template |
| self.documentation = proto.documentation |
| |
| class Rule(object): |
| """Representation of a rule used to render documentation templates.""" |
| |
| def __init__(self, proto): |
| self.__proto = proto |
| self.name = proto.name |
| self.type = proto.type |
| self.documentation = proto.documentation |
| self.example_documentation = proto.example_documentation |
| self.signature = self._get_signature(proto) |
| self.attributes = [] |
| for attribute in proto.attribute: |
| self.attributes.append(Attribute(attribute)) |
| self.outputs = [] |
| for output in proto.output: |
| self.outputs.append(Output(output)) |
| |
| parts = proto.documentation.split("\n\n") |
| self.short_documentation = parts[0] |
| |
| def _get_signature(self, proto): |
| """Returns the rule signature for this rule.""" |
| signature = proto.name + '(' |
| for i in range(len(proto.attribute)): |
| attr = proto.attribute[i] |
| signature += '<a href="#%s.%s">%s</a>' % (proto.name, attr.name, |
| attr.name) |
| if i < len(proto.attribute) - 1: |
| signature += ', ' |
| signature += ')' |
| return signature |
| |
| |
| class RuleSet(object): |
| """Representation of a rule set used to render documentation templates.""" |
| |
| def __init__(self, bzl_file, language, title, description, strip_prefix, |
| format): |
| self.bzl_file = bzl_file |
| file_basename = os.path.basename(bzl_file) |
| self.name = file_basename.replace('.bzl', '') |
| self.language = language |
| self.title = title if title else "%s Rules" % self.name |
| self.description = description |
| |
| # Generate output file name. |
| file_extension = 'html' if format == 'html' else 'md' |
| assert self.bzl_file.startswith(strip_prefix) |
| output_path = self.bzl_file.replace('.bzl', '') |
| self.output_file = output_path[len(strip_prefix):] |
| |
| # Populate all rules in this ruleset. |
| self.definitions = [] |
| self.rules = [] |
| self.repository_rules = [] |
| self.macros = [] |
| for rule_proto in language.rule: |
| definition = Rule(rule_proto) |
| self.definitions.append(definition) |
| if rule_proto.type == build_pb2.RuleDefinition.RULE: |
| self.rules.append(definition) |
| elif rule_proto.type == build_pb2.RuleDefinition.MACRO: |
| self.macros.append(definition) |
| else: |
| assert rule_proto.type == build_pb2.RuleDefinition.REPOSITORY_RULE |
| self.repository_rules.append(definition) |
| |
| def empty(self): |
| """Return True if there is nothing to document.""" |
| return not any([self.rules, |
| self.macros, |
| self.repository_rules]) |