1 # Copyright 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 from collections import defaultdict, Mapping
7 from third_party.json_schema_compiler import json_parse, idl_schema, idl_parser
10 def RemoveNoDocs(item):
11 '''Removes nodes that should not be rendered from an API schema.
13 if json_parse.IsDict(item):
14 if item.get('nodoc', False):
16 for key, value in item.items():
17 if RemoveNoDocs(value):
19 elif type(item) == list:
29 def DetectInlineableTypes(schema):
30 '''Look for documents that are only referenced once and mark them as inline.
31 Actual inlining is done by _InlineDocs.
33 if not schema.get('types'):
36 ignore = frozenset(('value', 'choices'))
37 refcounts = defaultdict(int)
38 # Use an explicit stack instead of recursion.
43 if isinstance(node, list):
45 elif isinstance(node, Mapping):
47 refcounts[node['$ref']] += 1
48 stack.extend(v for k, v in node.iteritems() if k not in ignore)
50 for type_ in schema['types']:
51 if not 'noinline_doc' in type_:
52 if refcounts[type_['id']] == 1:
53 type_['inline_doc'] = True
56 def InlineDocs(schema):
57 '''Replace '$ref's that refer to inline_docs with the json for those docs.
59 types = schema.get('types')
64 types_without_inline_doc = []
66 # Gather the types with inline_doc.
68 if type_.get('inline_doc'):
69 inline_docs[type_['id']] = type_
70 for k in ('description', 'id', 'inline_doc'):
73 types_without_inline_doc.append(type_)
74 schema['types'] = types_without_inline_doc
76 def apply_inline(node):
77 if isinstance(node, list):
80 elif isinstance(node, Mapping):
81 ref = node.get('$ref')
82 if ref and ref in inline_docs:
83 node.update(inline_docs[ref])
85 for k, v in node.iteritems():
91 def ProcessSchema(path, file_data):
92 '''Parses |file_data| using a method determined by checking the
93 extension of the file at the given |path|. Then, trims 'nodoc' and handles
94 inlineable types from the parsed schema data.
96 def trim_and_inline(schema, is_idl=False):
97 '''Modifies an API schema in place by removing nodes that shouldn't be
98 documented and inlining schema types that are only referenced once.
100 if RemoveNoDocs(schema):
101 # A return of True signifies that the entire schema should not be
102 # documented. Otherwise, only nodes that request 'nodoc' are removed.
105 DetectInlineableTypes(schema)
109 if path.endswith('.idl'):
110 idl = idl_schema.IDLSchema(idl_parser.IDLParser().ParseData(file_data))
111 return trim_and_inline(idl.process()[0], is_idl=True)
113 schemas = json_parse.Parse(file_data)
114 for schema in schemas:
115 # Schemas could consist of one API schema (data for a specific API file)
116 # or multiple (data from extension_api.json).
117 trim_and_inline(schema)