Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 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 model import PropertyType | 5 from model import PropertyType |
| 6 import code | 6 import code |
| 7 import cpp_util | 7 import cpp_util |
| 8 import os | |
| 9 | 8 |
| 10 class HGenerator(object): | 9 class HGenerator(object): |
| 11 """A .h generator for a namespace. | 10 """A .h generator for a namespace. |
| 12 """ | 11 """ |
| 13 def __init__(self, namespace, cpp_type_generator): | 12 def __init__(self, namespace, cpp_type_generator): |
| 14 self._cpp_type_generator = cpp_type_generator | 13 self._cpp_type_generator = cpp_type_generator |
| 15 self._namespace = namespace | 14 self._namespace = namespace |
| 16 self._target_namespace = ( | 15 self._target_namespace = ( |
| 17 self._cpp_type_generator.GetCppNamespaceName(self._namespace)) | 16 self._cpp_type_generator.GetCppNamespaceName(self._namespace)) |
| 18 | 17 |
| 19 def Generate(self): | 18 def Generate(self): |
| 20 """Generates a code.Code object with the .h for a single namespace. | 19 """Generates a code.Code object with the .h for a single namespace. |
| 21 """ | 20 """ |
| 22 c = code.Code() | 21 c = code.Code() |
| 23 (c.Append(cpp_util.CHROMIUM_LICENSE) | 22 (c.Append(cpp_util.CHROMIUM_LICENSE) |
| 24 .Append() | 23 .Append() |
| 25 .Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file) | 24 .Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file) |
| 26 .Append() | 25 .Append() |
| 27 ) | 26 ) |
| 28 | 27 |
| 29 ifndef_name = self._GenerateIfndefName() | 28 ifndef_name = self._GenerateIfndefName() |
| 30 (c.Append('#ifndef %s' % ifndef_name) | 29 (c.Append('#ifndef %s' % ifndef_name) |
| 31 .Append('#define %s' % ifndef_name) | 30 .Append('#define %s' % ifndef_name) |
| 32 .Append('#pragma once') | 31 .Append('#pragma once') |
| 33 .Append() | 32 .Append() |
| 34 .Append('#include <string>') | 33 .Append('#include <string>') |
| 35 .Append('#include <vector>') | 34 .Append('#include <vector>') |
| 36 .Append() | 35 .Append() |
| 37 .Append('#include "base/basictypes.h"') | 36 .Append('#include "base/basictypes.h"') |
| 37 .Append('#include "base/memory/linked_ptr.h"') | |
| 38 .Append('#include "base/memory/scoped_ptr.h"') | 38 .Append('#include "base/memory/scoped_ptr.h"') |
| 39 .Append('#include "base/values.h"') | 39 .Append('#include "base/values.h"') |
| 40 .Append() | 40 .Append() |
| 41 .Append('using base::Value;') | 41 .Append('using base::Value;') |
| 42 .Append('using base::DictionaryValue;') | 42 .Append('using base::DictionaryValue;') |
| 43 .Append('using base::ListValue;') | 43 .Append('using base::ListValue;') |
| 44 .Append() | 44 .Append() |
| 45 ) | 45 ) |
| 46 | 46 |
| 47 includes = self._cpp_type_generator.GenerateCppIncludes() | 47 c.Concat(self._cpp_type_generator.GetRootNamespaceStart()) |
| 48 if not includes.IsEmpty(): | 48 forward_declarations = ( |
| 49 (c.Concat(includes) | 49 self._cpp_type_generator.GenerateForwardDeclarations()) |
| 50 if not forward_declarations.IsEmpty(): | |
| 51 (c.Append() | |
| 52 .Concat(forward_declarations) | |
| 50 .Append() | 53 .Append() |
| 51 ) | 54 ) |
| 52 | 55 |
| 53 (c.Concat(self._cpp_type_generator.GetCppNamespaceStart()) | 56 (c.Concat(self._cpp_type_generator.GetNamespaceStart()) |
| 54 .Append() | 57 .Append() |
| 55 .Append('//') | 58 .Append('//') |
| 56 .Append('// Types') | 59 .Append('// Types') |
| 57 .Append('//') | 60 .Append('//') |
| 58 .Append() | 61 .Append() |
| 59 ) | 62 ) |
| 60 for type_ in self._namespace.types.values(): | 63 for type_ in self._namespace.types.values(): |
| 61 (c.Concat(self._GenerateType(type_)) | 64 (c.Concat(self._GenerateType(type_)) |
| 62 .Append() | 65 .Append() |
| 63 ) | 66 ) |
| 64 (c.Append('//') | 67 (c.Append('//') |
| 65 .Append('// Functions') | 68 .Append('// Functions') |
| 66 .Append('//') | 69 .Append('//') |
| 67 .Append() | 70 .Append() |
| 68 ) | 71 ) |
| 69 for function in self._namespace.functions.values(): | 72 for function in self._namespace.functions.values(): |
| 70 (c.Concat(self._GenerateFunction(function)) | 73 (c.Concat(self._GenerateFunction(function)) |
| 71 .Append() | 74 .Append() |
| 72 ) | 75 ) |
| 73 (c.Append() | 76 (c.Append() |
| 74 .Append() | 77 .Concat(self._cpp_type_generator.GetNamespaceEnd()) |
| 75 .Concat(self._cpp_type_generator.GetCppNamespaceEnd()) | 78 .Concat(self._cpp_type_generator.GetRootNamespaceEnd()) |
| 76 .Append() | 79 .Append() |
| 77 .Append('#endif // %s' % ifndef_name) | 80 .Append('#endif // %s' % ifndef_name) |
| 78 .Append() | 81 .Append() |
| 79 ) | 82 ) |
| 80 return c | 83 return c |
| 81 | 84 |
| 85 def _GenerateFields(self, props): | |
| 86 """Generates the field declarations when declaring a type. | |
| 87 """ | |
| 88 c = code.Code() | |
| 89 for prop in self._cpp_type_generator.GetExpandedChoicesInParams(props): | |
| 90 if prop.description: | |
| 91 c.Comment(prop.description) | |
| 92 c.Append('%s %s;' % ( | |
| 93 self._cpp_type_generator.GetType(prop, wrap_optional=True), | |
| 94 prop.unix_name)) | |
| 95 c.Append() | |
| 96 # Generate the enums needed for any fields with "choices" | |
| 97 for prop in [x for x in props if x.type_ == PropertyType.CHOICES]: | |
| 98 enum_name = self._cpp_type_generator.GetChoicesEnumType(prop) | |
| 99 c.Sblock('enum %s {' % enum_name) | |
|
not at google - send to devlin
2012/02/09 02:49:36
enum_name -> enum_type
(any reason you're not usi
calamity
2012/02/10 03:52:50
Done. Just got lazy I guess.
| |
| 100 c.Append(self._cpp_type_generator.GetChoiceEnumNoneValue(prop) + ',') | |
| 101 for choice in prop.choices.values(): | |
| 102 c.Append(self._cpp_type_generator.GetChoiceEnumValue(prop, choice.type_) | |
| 103 + ',') | |
| 104 (c.Eblock('};') | |
| 105 .Append() | |
| 106 .Append('%s %s_type;' % (enum_name, prop.unix_name)) | |
| 107 ) | |
| 108 return c | |
| 109 | |
| 82 def _GenerateType(self, type_, serializable=True): | 110 def _GenerateType(self, type_, serializable=True): |
| 83 """Generates a struct for a type. | 111 """Generates a struct for a type. |
| 84 """ | 112 """ |
| 85 classname = cpp_util.CppName(type_.name) | 113 classname = cpp_util.Classname(type_.name) |
| 86 c = code.Code() | 114 c = code.Code() |
| 87 if type_.description: | 115 if type_.description: |
| 88 c.Comment(type_.description) | 116 c.Comment(type_.description) |
| 89 (c.Sblock('struct %(classname)s {') | 117 (c.Sblock('struct %(classname)s {') |
| 90 .Append('~%(classname)s();') | 118 .Append('~%(classname)s();') |
| 91 .Append('%(classname)s();') | 119 .Append('%(classname)s();') |
| 92 .Append() | 120 .Append() |
| 93 ) | 121 .Concat(self._GenerateFields(type_.properties.values())) |
| 94 | 122 .Comment('Populates a %(classname)s object from a Value. Returns' |
| 95 for prop in type_.properties.values(): | 123 ' whether |out| was successfully populated.') |
| 96 if prop.description: | 124 .Append('static bool Populate(const Value& value, %(classname)s* out);') |
| 97 c.Comment(prop.description) | 125 .Append() |
| 98 if prop.optional: | |
| 99 c.Append('scoped_ptr<%s> %s;' % | |
| 100 (self._cpp_type_generator.GetType(prop, pad_for_generics=True), | |
| 101 prop.name)) | |
| 102 else: | |
| 103 c.Append('%s %s;' % | |
| 104 (self._cpp_type_generator.GetType(prop), prop.name)) | |
| 105 c.Append() | |
| 106 | |
| 107 (c.Comment('Populates a %(classname)s object from a Value. Returns' | |
| 108 ' whether |out| was successfully populated.') | |
| 109 .Append('static bool Populate(const Value& value, %(classname)s* out);') | |
| 110 .Append() | |
| 111 ) | 126 ) |
| 112 | 127 |
| 113 if serializable: | 128 if serializable: |
| 114 (c.Comment('Returns a new DictionaryValue representing the' | 129 (c.Comment('Returns a new DictionaryValue representing the' |
| 115 ' serialized form of this %(classname)s object. Passes' | 130 ' serialized form of this %(classname)s object. Passes' |
| 116 'ownership to caller.') | 131 'ownership to caller.') |
| 117 .Append('DictionaryValue* ToValue() const;') | 132 .Append('DictionaryValue* ToValue() const;') |
| 118 ) | 133 ) |
| 119 (c.Eblock() | 134 (c.Eblock() |
| 120 .Sblock(' private:') | 135 .Sblock(' private:') |
| 121 .Append('DISALLOW_COPY_AND_ASSIGN(%(classname)s);') | 136 .Append('DISALLOW_COPY_AND_ASSIGN(%(classname)s);') |
| 122 .Eblock('};') | 137 .Eblock('};') |
| 123 ) | 138 ) |
| 124 c.Substitute({'classname': classname}) | 139 c.Substitute({'classname': classname}) |
| 125 return c | 140 return c |
| 126 | 141 |
| 127 def _GenerateFunction(self, function): | 142 def _GenerateFunction(self, function): |
| 128 """Generates the structs for a function. | 143 """Generates the structs for a function. |
| 129 """ | 144 """ |
| 130 c = code.Code() | 145 c = code.Code() |
| 131 (c.Sblock('namespace %s {' % cpp_util.CppName(function.name)) | 146 (c.Sblock('namespace %s {' % cpp_util.Classname(function.name)) |
| 132 .Concat(self._GenerateFunctionParams(function)) | 147 .Concat(self._GenerateFunctionParams(function)) |
| 133 .Append() | 148 .Append() |
| 134 .Concat(self._GenerateFunctionResult(function)) | 149 .Concat(self._GenerateFunctionResult(function)) |
| 135 .Append() | 150 .Append() |
| 136 .Eblock('};') | 151 .Eblock('};') |
| 137 ) | 152 ) |
| 138 return c | 153 return c |
| 139 | 154 |
| 140 def _GenerateFunctionParams(self, function): | 155 def _GenerateFunctionParams(self, function): |
| 141 """Generates the struct for passing parameters into a function. | 156 """Generates the struct for passing parameters into a function. |
| 142 """ | 157 """ |
| 143 c = code.Code() | 158 c = code.Code() |
| 144 | 159 |
| 145 if function.params: | 160 if function.params: |
| 146 c.Sblock('struct Params {') | 161 c.Sblock('struct Params {') |
| 147 for param in function.params: | 162 for param in function.params: |
| 148 if param.description: | 163 if param.description: |
| 149 c.Comment(param.description) | 164 c.Comment(param.description) |
| 150 if param.type_ == PropertyType.OBJECT: | 165 if param.type_ == PropertyType.OBJECT: |
| 151 c.Concat(self._GenerateType(param, serializable=False)) | 166 c.Concat(self._GenerateType(param, serializable=False)) |
| 152 c.Append() | 167 c.Append() |
| 153 for param in function.params: | 168 (c.Concat(self._GenerateFields(function.params)) |
| 154 c.Append('%s %s;' % | |
| 155 (self._cpp_type_generator.GetType(param), param.name)) | |
| 156 | |
| 157 (c.Append() | |
| 158 .Append('~Params();') | 169 .Append('~Params();') |
| 159 .Append() | 170 .Append() |
| 160 .Append('static scoped_ptr<Params> Create(const ListValue& args);') | 171 .Append('static scoped_ptr<Params> Create(const ListValue& args);') |
| 161 .Eblock() | 172 .Eblock() |
| 162 .Sblock(' private:') | 173 .Sblock(' private:') |
| 163 .Append('Params();') | 174 .Append('Params();') |
| 164 .Append() | 175 .Append() |
| 165 .Append('DISALLOW_COPY_AND_ASSIGN(Params);') | 176 .Append('DISALLOW_COPY_AND_ASSIGN(Params);') |
| 177 .Eblock('};') | |
| 166 ) | 178 ) |
| 167 | 179 |
| 168 c.Eblock('};') | |
| 169 | |
| 170 return c | 180 return c |
| 171 | 181 |
| 172 def _GenerateFunctionResult(self, function): | 182 def _GenerateFunctionResult(self, function): |
| 173 """Generates the struct for passing a function's result back. | 183 """Generates the struct for passing a function's result back. |
| 174 """ | 184 """ |
| 175 # TODO(calamity): Handle returning an object | |
| 176 c = code.Code() | 185 c = code.Code() |
| 177 | 186 |
| 178 param = function.callback.param | |
| 179 # TODO(calamity): Put this description comment in less stupid place | |
| 180 if param.description: | |
| 181 c.Comment(param.description) | |
| 182 (c.Append('class Result {') | 187 (c.Append('class Result {') |
| 183 .Sblock(' public:') | 188 .Sblock(' public:') |
| 184 ) | 189 ) |
| 185 arg = '' | 190 params = function.callback.params |
| 186 # TODO(calamity): handle object | 191 if not params: |
| 187 if param: | 192 c.Append('static Value* Create();') |
| 188 if param.type_ == PropertyType.REF: | 193 else: |
| 189 arg = 'const %(type)s& %(name)s' | 194 # If there is a single parameter, this is straightforward. However, if |
| 190 else: | 195 # the callback parameter is of 'choices', this generates a Create method |
| 196 # for each choice. This works because only 1 choice can be returned at a | |
| 197 # time. | |
| 198 for param in self._cpp_type_generator.GetExpandedChoicesInParams(params): | |
| 191 arg = 'const %(type)s %(name)s' | 199 arg = 'const %(type)s %(name)s' |
| 192 arg = arg % { | 200 if param.type_ == PropertyType.REF: |
| 193 'type': self._cpp_type_generator.GetType(param), | 201 arg = 'const %(type)s& %(name)s' |
| 194 'name': param.name | 202 arg %= { |
| 195 } | 203 'type': self._cpp_type_generator.GetType(param, wrap_optional=True), |
| 196 (c.Append('static Value* Create(%s);' % arg) | 204 'name': param.unix_name, |
| 197 .Eblock() | 205 } |
| 198 .Sblock(' private:') | 206 if param.description: |
| 199 .Append('Result() {};') | 207 c.Comment(param.description) |
| 200 .Append('DISALLOW_COPY_AND_ASSIGN(Result);') | 208 c.Append('static Value* Create(%s);' % arg) |
| 201 .Eblock('};') | 209 (c.Eblock() |
| 210 .Sblock(' private:') | |
| 211 .Append('Result() {};') | |
| 212 .Append('DISALLOW_COPY_AND_ASSIGN(Result);') | |
| 213 .Eblock('};') | |
| 202 ) | 214 ) |
| 203 | 215 |
| 204 return c | 216 return c |
| 205 | 217 |
| 206 def _GenerateIfndefName(self): | 218 def _GenerateIfndefName(self): |
| 207 """Formats a path and filename as a #define name. | 219 """Formats a path and filename as a #define name. |
| 208 | 220 |
| 209 e.g chrome/extensions/gen, file.h becomes CHROME_EXTENSIONS_GEN_FILE_H__. | 221 e.g chrome/extensions/gen, file.h becomes CHROME_EXTENSIONS_GEN_FILE_H__. |
| 210 """ | 222 """ |
| 211 return (('%s_%s_H__' % | 223 return (('%s/%s_H__' % |
| 212 (self._namespace.source_file_dir, self._target_namespace)) | 224 (self._namespace.source_file_dir, self._target_namespace)) |
| 213 .upper().replace(os.sep, '_')) | 225 .upper().replace('/', '_')) |
| 214 | 226 |
| OLD | NEW |