Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(427)

Unified Diff: tools/nixysa/nixysa/cpp_header_generator.py

Issue 2043006: WTF NPAPI extension. Early draft. Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/nixysa/nixysa/codegen.sh ('k') | tools/nixysa/nixysa/cpp_utils.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/nixysa/nixysa/cpp_header_generator.py
===================================================================
--- tools/nixysa/nixysa/cpp_header_generator.py (revision 0)
+++ tools/nixysa/nixysa/cpp_header_generator.py (revision 0)
@@ -0,0 +1,363 @@
+#!/usr/bin/python2.4
+#
+# Copyright 2008 Google Inc.
+#
+# 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.
+
+"""C++ header file generator.
+
+This module generates C++ header file for a javascript
+documentation file from the parsed syntax tree.
+"""
+
+import cpp_utils
+import gflags
+import java_utils
+import naming
+
+
+class UndocumentedError(Exception):
+ """Error raised when a member is undocumented."""
+
+ def __init__(self, obj):
+ Exception.__init__(self)
+ self.object = obj
+
+
+class CPPHeaderGenerator(object):
+ """Header generator class.
+
+ This class takes care of the details of generating a C++ header file
+ containing all the definitions from a syntax tree. This particular
+ header generator does so with a slant on javascript. This means no
+ virtual, static, void, etc.
+
+ It contains a list of functions named after each of the Definition classes in
+ syntax_tree, with a common signature. The appropriate function will be called
+ for each definition, to generate the code for that definition.
+
+ Attributes:
+ _output_dir: output directory
+ force_documentation: whether to force all members to have documentation
+ """
+
+ def __init__(self, output_dir):
+ self._output_dir = output_dir
+ self.force_documentation = gflags.FLAGS['force-docs'].value
+
+ def GetSectionFromAttributes(self, parent_section, defn):
+ """Gets the code section appropriate for a given definition.
+
+ Classes have 3 definition sections: private, protected and public. This
+ function will pick one of the sections, based on the attributes of the
+ definition, if its parent is a class. For other scopes (namespaces) it will
+ return the parent scope main section.
+
+ Args:
+ parent_section: the main section for the parent scope.
+ defn: the definition.
+
+ Returns:
+ the appropriate section.
+ """
+ if defn.parent and defn.parent.defn_type == 'Class':
+ if 'private' in defn.attributes:
+ return parent_section.GetSection('private:') or parent_section
+ elif 'protected' in defn.attributes:
+ return parent_section.GetSection('protected:') or parent_section
+ else:
+ return parent_section.GetSection('public:') or parent_section
+ else:
+ return parent_section
+
+ def Verbatim(self, parent_section, scope, obj):
+ """Generates the code for a Verbatim definition.
+
+ Verbatim definitions being written for a particular type of output file,
+ this function will check the 'verbatim' attribute, and only emit the
+ verbatim code if it is 'cpp_header'.
+
+ Args:
+ parent_section: the main section of the parent scope.
+ scope: the parent scope.
+ obj: the Verbatim definition.
+
+ Returns:
+ a list of (boolean, Definition) pairs, of all the types that need
+ to be declared (boolean is False) or defined (boolean is True) before
+ this definition.
+ """
+ scope = scope # silence gpylint.
+ try:
+ if obj.attributes['verbatim'] == 'cpp_header':
+ section = self.GetSectionFromAttributes(parent_section, obj)
+ section.EmitCode(obj.text)
+ except KeyError:
+ source = obj.source
+ print ('%s:%d ignoring verbatim with no verbatim attribute' %
+ (source.file.source, source.line))
+
+ def Typedef(self, parent_section, scope, obj):
+ """Generates the code for a Typedef definition.
+
+ Args:
+ parent_section: the main section of the parent scope.
+ scope: the parent scope.
+ obj: the Typedef definition.
+ """
+ section = self.GetSectionFromAttributes(parent_section, obj)
+ bm = obj.type_defn.binding_model
+ type_string = bm.JavaMemberString(scope, obj.type_defn)
+ section.EmitCode('typedef %s %s;' % (type_string, obj.name))
+
+ def Variable(self, parent_section, scope, obj):
+ """Generates the code for a Variable definition.
+
+ This function will generate the member/global variable declaration, as well
+ as the setter/getter functions if specified in the attributes.
+
+ Args:
+ parent_section: the main section of the parent scope.
+ scope: the parent scope.
+ obj: the Variable definition.
+ """
+ member_section = self.GetSectionFromAttributes(parent_section, obj)
+
+ bm = obj.type_defn.binding_model
+ type_string = bm.JavaMemberString(scope, obj.type_defn)
+ # Note: There is no static in javascript
+ field_name = naming.Normalize(obj.name, naming.Java)
+ if 'getter' in obj.attributes and 'setter' not in obj.attributes:
+ self.Documentation(member_section, obj,
+ 'This property is read-only.')
+ elif 'getter' not in obj.attributes and 'setter' in obj.attributes:
+ self.Documentation(member_section, obj,
+ 'This property is write-only.')
+ else:
+ self.Documentation(member_section, obj, '')
+ member_section.EmitCode('%s %s;' % (type_string, field_name))
+ # Note: There are no getter/setter in javascript
+
+ def Function(self, parent_section, scope, obj):
+ """Generates the code for a Function definition.
+
+ Args:
+ parent_section: the main section of the parent scope.
+ scope: the parent scope.
+ obj: the Function definition.
+ """
+ section = self.GetSectionFromAttributes(parent_section, obj)
+ self.Documentation(section, obj, '')
+ prototype = java_utils.GetFunctionPrototype(scope, obj)
+ section.EmitCode(prototype + ';')
+
+ def Callback(self, parent_section, scope, obj):
+ """Generates the code for a Callback definition.
+
+ Args:
+ parent_section: the main section of the parent scope.
+ scope: the parent scope.
+ obj: the Class definition.
+ """
+ parent_section, scope, obj = parent_section, scope, obj # silence gpylint
+ # TODO: implement this. Do we want to generate the C++ callback object
+ # (either through a CallbackN<A0, A1, ...> typedef, or explicitly), or
+ # something else that could be more useful to generate CPP docs ?
+
+ def Class(self, parent_section, scope, obj):
+ """Generates the code for a Class definition.
+
+ This function will recursively generate the code for all the definitions
+ inside the class. These definitions will be output into one of 3 sections
+ (private, protected, public), depending on their attributes. These
+ individual sections will only be output if they are not empty.
+
+ Args:
+ parent_section: the main section of the parent scope.
+ scope: the parent scope.
+ obj: the Class definition.
+ """
+ self.Documentation(parent_section, obj, '')
+ section = self.GetSectionFromAttributes(parent_section, obj).CreateSection(
+ obj.name)
+ if obj.base_type:
+ bm = obj.base_type.binding_model
+ type_string = bm.JavaMemberString(scope, obj.base_type)
+ section.EmitCode('class %s : public %s {' % (obj.name, type_string))
+ else:
+ section.EmitCode('class %s {' % obj.name)
+ public_section = section.CreateSection('public:')
+ protected_section = section.CreateSection('protected:')
+ private_section = section.CreateSection('private:')
+ self.DefinitionList(section, obj, obj.defn_list)
+ if not public_section.IsEmpty():
+ public_section.AddPrefix('public:')
+ if not protected_section.IsEmpty():
+ protected_section.AddPrefix('protected:')
+ if not private_section.IsEmpty():
+ private_section.AddPrefix('private:')
+ section.EmitCode('};')
+
+ def Namespace(self, parent_section, scope, obj):
+ """Generates the code for a Namespace definition.
+
+ This function will recursively generate the code for all the definitions
+ inside the namespace.
+
+ Args:
+ parent_section: the main section of the parent scope.
+ scope: the parent scope.
+ obj: the Namespace definition.
+ """
+ scope = scope # silence gpylint.
+ self.Documentation(parent_section, obj, '')
+ parent_section.PushNamespace(obj.name)
+ self.DefinitionList(parent_section, obj, obj.defn_list)
+ parent_section.PopNamespace()
+
+ def Typename(self, parent_section, scope, obj):
+ """Generates the code for a Typename definition.
+
+ Since typenames (undefined types) cannot be expressed in C++, this function
+ will not output code. The definition may be output with a verbatim section.
+
+ Args:
+ parent_section: the main section of the parent scope.
+ scope: the parent scope.
+ obj: the Typename definition.
+ """
+ # silence gpylint.
+ parent_section, scope, obj = parent_section, scope, obj
+
+ def Enum(self, parent_section, scope, obj):
+ """Generates the code for an Enum definition.
+
+ Args:
+ parent_section: the main section of the parent scope.
+ scope: the parent scope.
+ obj: the Enum definition.
+ """
+ scope = scope # silence gpylint.
+ section = self.GetSectionFromAttributes(parent_section, obj)
+ self.Documentation(parent_section, obj, '')
+ section.EmitCode('enum %s {' % obj.name)
+ for value in obj.values:
+ if value.value is None:
+ section.EmitCode('%s,' % value.name)
+ else:
+ section.EmitCode('%s = %s,' % (value.name, value.value))
+ section.EmitCode('};')
+
+ def DefinitionList(self, parent_section, scope, defn_list):
+ """Generates the code for all the definitions in a list.
+
+ Args:
+ parent_section: the main section of the parent scope.
+ scope: the parent scope.
+ defn_list: the list of definitions.
+ """
+ for obj in defn_list:
+ if 'nojs' in obj.attributes:
+ continue
+ func = getattr(self, obj.defn_type)
+ func(parent_section, scope, obj)
+
+ def Documentation(self, parent_section, obj, extra_doc):
+ """Generates the documentation code.
+
+ Args:
+ parent_section: the main section of the parent scope.
+ obj: the object to be documented; may be class, function, enum or field.
+ extra_doc: extra documenation information to be put in comments
+ Raises:
+ UndocumentedError: an error if there is no documentation
+ """
+ try:
+ section = self.GetSectionFromAttributes(parent_section, obj)
+ comment_lines = obj.attributes['__docs'].splitlines()
+ # Break up text and insert comment formatting
+ section.EmitCode('/*! ')
+ for line in comment_lines:
+ section.EmitCode('%s' % (line))
+ section.EmitCode('%s' % (extra_doc))
+ section.EmitCode('*/')
+
+ except KeyError:
+ # catch the error when __docs does not exist
+ if self.force_documentation:
+ source = obj.source
+ print ('%s:%d Documentation not found' % (source.file.source,
+ source.line))
+ raise UndocumentedError('Documentation not found.')
+
+ def FieldFunctionDocumentation(self, member_section, description,
+ type_string, field_name):
+ """Automatically generate the get/set function documentation code.
+
+ Args:
+ member_section: the main section of the getter/setter scope.
+ description: describes the field function.
+ type_string: string defining field type.
+ field_name: getter/setter field name.
+ """
+ member_section.EmitCode('/*!')
+ member_section.EmitCode('* %s for %s %s' %
+ (description, type_string, field_name))
+ member_section.EmitCode('*/')
+
+ def Generate(self, idl_file, namespace, defn_list):
+ """Generates the header file.
+
+ Args:
+ idl_file: the source IDL file containing the definitions, as a
+ idl_parser.File instance.
+ namespace: a Definition for the global namespace.
+ defn_list: the list of top-level definitions.
+
+ Returns:
+ a cpp_utils.CppFileWriter that contains the C++ header file code.
+
+ Raises:
+ CircularDefinition: circular definitions were found in the file.
+ """
+ writer = cpp_utils.CppFileWriter('%s/%s' % (self._output_dir,
+ idl_file.header), True)
+ code_section = writer.CreateSection('defns')
+ self.DefinitionList(code_section, namespace, defn_list)
+ return writer
+
+
+def ProcessFiles(output_dir, pairs, namespace):
+ """Generates the headers for all input files.
+
+ Args:
+ output_dir: the output directory.
+ pairs: a list of (idl_parser.File, syntax_tree.Definition list) describing
+ the list of top-level definitions in each source file.
+ namespace: a syntax_tree.Namespace for the global namespace.
+
+ Returns:
+ a list of cpp_utils.CppFileWriter, one for each output header file.
+ """
+ generator = CPPHeaderGenerator(output_dir)
+ writer_list = []
+ for (f, defn) in pairs:
+ writer_list.append(generator.Generate(f, namespace, defn))
+ return writer_list
+
+
+def main():
+ pass
+
+if __name__ == '__main__':
+ main()
Property changes on: tools/nixysa/nixysa/cpp_header_generator.py
___________________________________________________________________
Added: svn:eol-style
+ LF
« no previous file with comments | « tools/nixysa/nixysa/codegen.sh ('k') | tools/nixysa/nixysa/cpp_utils.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698