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
8 from third_party
.json_schema_compiler
import json_parse
, idl_schema
, idl_parser
11 def RemoveNoDocs(item
):
12 '''Removes nodes that should not be rendered from an API schema.
14 if json_parse
.IsDict(item
):
15 if item
.get('nodoc', False):
17 for key
, value
in item
.items():
18 if RemoveNoDocs(value
):
20 elif type(item
) == list:
30 def DetectInlineableTypes(schema
):
31 '''Look for documents that are only referenced once and mark them as inline.
32 Actual inlining is done by _InlineDocs.
34 if not schema
.get('types'):
37 ignore
= frozenset(('value', 'choices'))
38 refcounts
= defaultdict(int)
39 # Use an explicit stack instead of recursion.
44 if isinstance(node
, list):
46 elif isinstance(node
, Mapping
):
48 refcounts
[node
['$ref']] += 1
49 stack
.extend(v
for k
, v
in node
.iteritems() if k
not in ignore
)
51 for type_
in schema
['types']:
52 if not 'noinline_doc' in type_
:
53 if refcounts
[type_
['id']] == 1:
54 type_
['inline_doc'] = True
57 def InlineDocs(schema
):
58 '''Replace '$ref's that refer to inline_docs with the json for those docs.
60 types
= schema
.get('types')
65 types_without_inline_doc
= []
67 # Gather the types with inline_doc.
69 if type_
.get('inline_doc'):
70 inline_docs
[type_
['id']] = type_
71 for k
in ('description', 'id', 'inline_doc'):
74 types_without_inline_doc
.append(type_
)
75 schema
['types'] = types_without_inline_doc
77 def apply_inline(node
):
78 if isinstance(node
, list):
81 elif isinstance(node
, Mapping
):
82 ref
= node
.get('$ref')
83 if ref
and ref
in inline_docs
:
84 node
.update(inline_docs
[ref
])
86 for k
, v
in node
.iteritems():
92 def ProcessSchema(path
, file_data
):
93 '''Parses |file_data| using a method determined by checking the
94 extension of the file at the given |path|. Then, trims 'nodoc' and handles
95 inlineable types from the parsed schema data.
97 def trim_and_inline(schema
, is_idl
=False):
98 '''Modifies an API schema in place by removing nodes that shouldn't be
99 documented and inlining schema types that are only referenced once.
101 if RemoveNoDocs(schema
):
102 # A return of True signifies that the entire schema should not be
103 # documented. Otherwise, only nodes that request 'nodoc' are removed.
106 DetectInlineableTypes(schema
)
110 if path
.endswith('.idl'):
111 idl
= idl_schema
.IDLSchema(idl_parser
.IDLParser().ParseData(file_data
))
112 # Wrap the result in a list so that it behaves like JSON API data.
113 return [trim_and_inline(idl
.process()[0], is_idl
=True)]
116 schemas
= json_parse
.Parse(file_data
)
118 raise ValueError('Cannot parse "%s" as JSON:\n%s' %
119 (path
, traceback
.format_exc()))
120 for schema
in schemas
:
121 # Schemas could consist of one API schema (data for a specific API file)
122 # or multiple (data from extension_api.json).
123 trim_and_inline(schema
)