OLD | NEW |
1 # Copyright 2015 The Chromium Authors. All rights reserved. | 1 # Copyright 2015 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 from code import Code | 5 from code import Code |
6 from model import PropertyType | 6 from model import PropertyType |
7 | 7 |
8 from datetime import datetime | 8 from datetime import datetime |
9 | 9 |
10 LICENSE = """// Copyright %s The Chromium Authors. All rights reserved. | 10 LICENSE = """// Copyright %s The Chromium Authors. All rights reserved. |
(...skipping 12 matching lines...) Expand all Loading... |
23 def GetLicense(self): | 23 def GetLicense(self): |
24 """Returns the license text for JS extern and interface files. | 24 """Returns the license text for JS extern and interface files. |
25 """ | 25 """ |
26 return (LICENSE % datetime.now().year) | 26 return (LICENSE % datetime.now().year) |
27 | 27 |
28 def GetInfo(self, tool): | 28 def GetInfo(self, tool): |
29 """Returns text describing how the file was generated. | 29 """Returns text describing how the file was generated. |
30 """ | 30 """ |
31 return (INFO % tool) | 31 return (INFO % tool) |
32 | 32 |
33 def GenerateObjectDefinition(self, namespace_name, properties): | 33 def AppendObjectDefinition(self, c, namespace_name, properties, |
| 34 new_line=True): |
34 """Given an OrderedDict of properties, returns a Code containing the | 35 """Given an OrderedDict of properties, returns a Code containing the |
35 description of an object. | 36 description of an object. |
36 """ | 37 """ |
37 if not properties: return Code() | 38 if not properties: return |
38 | 39 |
39 c = Code() | 40 c.Sblock('{', new_line=new_line) |
40 c.Sblock('{') | |
41 first = True | 41 first = True |
42 for field, prop in properties.items(): | 42 for field, prop in properties.items(): |
43 # Avoid trailing comma. | 43 # Avoid trailing comma. |
44 # TODO(devlin): This will be unneeded, if/when | 44 # TODO(devlin): This will be unneeded, if/when |
45 # https://github.com/google/closure-compiler/issues/796 is fixed. | 45 # https://github.com/google/closure-compiler/issues/796 is fixed. |
46 if not first: | 46 if not first: |
47 c.Append(',', new_line=False) | 47 c.Append(',', new_line=False) |
48 first = False | 48 first = False |
49 js_type = self._TypeToJsType(namespace_name, prop.type_) | 49 js_type = self._TypeToJsType(namespace_name, prop.type_) |
50 if prop.optional: | 50 if prop.optional: |
51 js_type = (Code(). | 51 js_type = (Code().Append('(') |
52 Append('('). | 52 .Concat(js_type, new_line=False) |
53 Concat(js_type, new_line=False). | 53 .Append('|undefined)', new_line=False)) |
54 Append('|undefined)', new_line=False)) | |
55 c.Append('%s: ' % field, strip_right=False) | 54 c.Append('%s: ' % field, strip_right=False) |
56 c.Concat(js_type, new_line=False) | 55 c.Concat(js_type, new_line=False) |
57 | 56 |
58 c.Eblock('}') | 57 c.Eblock('}') |
59 | 58 |
60 return c | 59 def AppendFunctionJsDoc(self, c, namespace_name, function): |
61 | 60 """Appends the documentation for a function as a Code. |
62 def GenerateFunctionJsDoc(self, namespace_name, function): | |
63 """Generates the documentation for a function as a Code. | |
64 | 61 |
65 Returns an empty code object if the object has no documentation. | 62 Returns an empty code object if the object has no documentation. |
66 """ | 63 """ |
67 c = Code() | |
68 c.Sblock(line='/**', line_prefix=' * ') | 64 c.Sblock(line='/**', line_prefix=' * ') |
69 | 65 |
70 if function.description: | 66 if function.description: |
71 c.Comment(function.description, comment_prefix='') | 67 c.Comment(function.description, comment_prefix='') |
72 | 68 |
73 def append_field(c, tag, js_type, name, optional, description): | 69 def append_field(c, tag, js_type, name, optional, description): |
74 c.Append('@%s {' % tag) | 70 c.Append('@%s {' % tag) |
75 c.Concat(js_type, new_line=False) | 71 c.Concat(js_type, new_line=False) |
76 if optional: | 72 if optional: |
77 c.Append('=', new_line=False) | 73 c.Append('=', new_line=False) |
78 c.Append('} %s' % name, new_line=False) | 74 c.Append('}', new_line=False) |
| 75 c.Comment(' %s' % name, comment_prefix='', wrap_indent=4, new_line=False) |
79 if description: | 76 if description: |
80 c.Comment(' %s' % description, comment_prefix='', | 77 c.Comment(' %s' % description, comment_prefix='', |
81 wrap_indent=4, new_line=False) | 78 wrap_indent=4, new_line=False) |
82 | 79 |
83 for param in function.params: | 80 for param in function.params: |
84 append_field(c, 'param', self._TypeToJsType(namespace_name, param.type_), | 81 append_field(c, 'param', |
| 82 self._TypeToJsType(namespace_name, param.type_), |
85 param.name, param.optional, param.description) | 83 param.name, param.optional, param.description) |
86 | 84 |
87 if function.callback: | 85 if function.callback: |
88 append_field(c, 'param', | 86 append_field(c, 'param', |
89 self._FunctionToJsFunction(namespace_name, | 87 self._FunctionToJsFunction(namespace_name, |
90 function.callback), | 88 function.callback), |
91 function.callback.name, function.callback.optional, | 89 function.callback.name, function.callback.optional, |
92 function.callback.description) | 90 function.callback.description) |
93 | 91 |
94 if function.returns: | 92 if function.returns: |
95 append_field(c, 'return', | 93 append_field(c, 'return', |
96 self._TypeToJsType(namespace_name, function.returns), | 94 self._TypeToJsType(namespace_name, function.returns), |
97 '', False, function.returns.description) | 95 '', False, function.returns.description) |
98 | 96 |
99 if function.deprecated: | 97 if function.deprecated: |
100 c.Append('@deprecated %s' % function.deprecated) | 98 c.Append('@deprecated %s' % function.deprecated) |
101 | 99 |
102 c.Append(self.GenerateSeeLink(namespace_name, 'method', function.name)) | 100 c.Append(self.GetSeeLink(namespace_name, 'method', function.name)) |
103 | 101 |
104 c.Eblock(' */') | 102 c.Eblock(' */') |
105 return c | |
106 | 103 |
107 def _FunctionToJsFunction(self, namespace_name, function): | 104 def _FunctionToJsFunction(self, namespace_name, function): |
108 """Converts a model.Function to a JS type (i.e., function([params])...)""" | 105 """Converts a model.Function to a JS type (i.e., function([params])...)""" |
109 c = Code() | 106 c = Code() |
110 c.Append('function(') | 107 c.Append('function(') |
111 for i, param in enumerate(function.params): | 108 for i, param in enumerate(function.params): |
112 c.Concat(self._TypeToJsType(namespace_name, param.type_), new_line=False) | 109 c.Concat(self._TypeToJsType(namespace_name, param.type_), new_line=False) |
113 if i is not len(function.params) - 1: | 110 if i is not len(function.params) - 1: |
114 c.Append(', ', new_line=False, strip_right=False) | 111 c.Append(', ', new_line=False, strip_right=False) |
115 c.Append('):', new_line=False) | 112 c.Append('):', new_line=False) |
116 | 113 |
117 if function.returns: | 114 if function.returns: |
118 c.Concat(self._TypeToJsType(namespace_name, function.returns), | 115 c.Concat(self._TypeToJsType(namespace_name, function.returns), |
119 new_line=False) | 116 new_line=False) |
120 else: | 117 else: |
121 c.Append('void', new_line=False) | 118 c.Append('void', new_line=False) |
122 | 119 |
123 return c | 120 return c |
124 | 121 |
125 def _TypeToJsType(self, namespace_name, js_type): | 122 def _TypeToJsType(self, namespace_name, js_type): |
126 """Converts a model.Type to a JS type (number, Array, etc.)""" | 123 """Converts a model.Type to a JS type (number, Array, etc.)""" |
127 if js_type.property_type in (PropertyType.INTEGER, PropertyType.DOUBLE): | 124 if js_type.property_type in (PropertyType.INTEGER, PropertyType.DOUBLE): |
128 return Code().Append('number') | 125 return Code().Append('number') |
129 if js_type.property_type is PropertyType.OBJECT: | 126 if js_type.property_type is PropertyType.OBJECT: |
130 if js_type.properties: | 127 if js_type.properties: |
131 return self.GenerateObjectDefinition(namespace_name, | 128 c = Code() |
132 js_type.properties) | 129 self.AppendObjectDefinition(c, namespace_name, js_type.properties) |
| 130 return c |
133 return Code().Append('Object') | 131 return Code().Append('Object') |
134 if js_type.property_type is PropertyType.ARRAY: | 132 if js_type.property_type is PropertyType.ARRAY: |
135 return (Code().Append('!Array<'). | 133 return (Code().Append('!Array<'). |
136 Concat(self._TypeToJsType(namespace_name, js_type.item_type), | 134 Concat(self._TypeToJsType(namespace_name, js_type.item_type), |
137 new_line=False). | 135 new_line=False). |
138 Append('>', new_line=False)) | 136 Append('>', new_line=False)) |
139 if js_type.property_type is PropertyType.REF: | 137 if js_type.property_type is PropertyType.REF: |
140 ref_type = '!chrome.%s.%s' % (namespace_name, js_type.ref_type) | 138 ref_type = '!chrome.%s.%s' % (namespace_name, js_type.ref_type) |
141 return Code().Append(ref_type) | 139 return Code().Append(ref_type) |
142 if js_type.property_type is PropertyType.CHOICES: | 140 if js_type.property_type is PropertyType.CHOICES: |
143 c = Code() | 141 c = Code() |
144 c.Append('(') | 142 c.Append('(') |
145 for i, choice in enumerate(js_type.choices): | 143 for i, choice in enumerate(js_type.choices): |
146 c.Concat(self._TypeToJsType(namespace_name, choice), new_line=False) | 144 c.Concat(self._TypeToJsType(namespace_name, choice), new_line=False) |
147 if i is not len(js_type.choices) - 1: | 145 if i is not len(js_type.choices) - 1: |
148 c.Append('|', new_line=False) | 146 c.Append('|', new_line=False) |
149 c.Append(')', new_line=False) | 147 c.Append(')', new_line=False) |
150 return c | 148 return c |
151 if js_type.property_type is PropertyType.FUNCTION: | 149 if js_type.property_type is PropertyType.FUNCTION: |
152 return self._FunctionToJsFunction(namespace_name, js_type.function) | 150 return self._FunctionToJsFunction(namespace_name, js_type.function) |
153 if js_type.property_type is PropertyType.ANY: | 151 if js_type.property_type is PropertyType.ANY: |
154 return Code().Append('*') | 152 return Code().Append('*') |
155 if js_type.property_type.is_fundamental: | 153 if js_type.property_type.is_fundamental: |
156 return Code().Append(js_type.property_type.name) | 154 return Code().Append(js_type.property_type.name) |
157 return Code().Append('?') # TODO(tbreisacher): Make this more specific. | 155 return Code().Append('?') # TODO(tbreisacher): Make this more specific. |
158 | 156 |
159 def GenerateSeeLink(self, namespace_name, object_type, object_name): | 157 def GetSeeLink(self, namespace_name, object_type, object_name): |
160 """Generates a @see link for a given API 'object' (type, method, or event). | 158 """Returns a @see link for a given API 'object' (type, method, or event). |
161 """ | 159 """ |
162 | 160 |
163 # NOTE(devlin): This is kind of a hack. Some APIs will be hosted on | 161 # NOTE(devlin): This is kind of a hack. Some APIs will be hosted on |
164 # developer.chrome.com/apps/ instead of /extensions/, and some APIs have | 162 # developer.chrome.com/apps/ instead of /extensions/, and some APIs have |
165 # '.'s in them (like app.window), which should resolve to 'app_window'. | 163 # '.'s in them (like app.window), which should resolve to 'app_window'. |
166 # Luckily, the doc server has excellent url resolution, and knows exactly | 164 # Luckily, the doc server has excellent url resolution, and knows exactly |
167 # what we mean. This saves us from needing any complicated logic here. | 165 # what we mean. This saves us from needing any complicated logic here. |
168 return ('@see https://developer.chrome.com/extensions/%s#%s-%s' % | 166 return ('@see https://developer.chrome.com/extensions/%s#%s-%s' % |
169 (namespace_name, object_type, object_name)) | 167 (namespace_name, object_type, object_name)) |
OLD | NEW |