1f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#!/usr/bin/env python
2f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#
3f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch# Copyright 2008 Google Inc.  All Rights Reserved.
4f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#
5f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch# Licensed under the Apache License, Version 2.0 (the "License");
6f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch# you may not use this file except in compliance with the License.
7f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch# You may obtain a copy of the License at
8f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#
9f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#      http://www.apache.org/licenses/LICENSE-2.0
10f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#
11f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch# Unless required by applicable law or agreed to in writing, software
12f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch# distributed under the License is distributed on an "AS IS" BASIS,
13f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch# See the License for the specific language governing permissions and
15f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch# limitations under the License.
16f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
17f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch"""Generate Google Mock classes from base classes.
18f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
19f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochThis program will read in a C++ source file and output the Google Mock
20f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochclasses for the specified classes.  If no class is specified, all
21f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochclasses in the source file are emitted.
22f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
23f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochUsage:
24f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  gmock_class.py header-file.h [ClassName]...
25f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
26f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochOutput is sent to stdout.
27f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch"""
28f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
29f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch__author__ = 'nnorwitz@google.com (Neal Norwitz)'
30f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
31f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
32f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochimport os
33f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochimport re
34f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochimport sys
35f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
36f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochfrom cpp import ast
37f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochfrom cpp import utils
38f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
39f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch# Preserve compatibility with Python 2.3.
40f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochtry:
41f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  _dummy = set
42f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochexcept NameError:
43f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  import sets
44f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  set = sets.Set
45f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
46f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch_VERSION = (1, 0, 1)  # The version of this script.
47f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch# How many spaces to indent.  Can set me with the INDENT environment variable.
48f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch_INDENT = 2
49f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
50f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
51f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochdef _GenerateMethods(output_lines, source, class_node):
52f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  function_type = (ast.FUNCTION_VIRTUAL | ast.FUNCTION_PURE_VIRTUAL |
53f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                   ast.FUNCTION_OVERRIDE)
54f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ctor_or_dtor = ast.FUNCTION_CTOR | ast.FUNCTION_DTOR
55f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  indent = ' ' * _INDENT
56f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
57f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  for node in class_node.body:
58f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    # We only care about virtual functions.
59f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (isinstance(node, ast.Function) and
60f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        node.modifiers & function_type and
61f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        not node.modifiers & ctor_or_dtor):
62f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      # Pick out all the elements we need from the original function.
63f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      const = ''
64f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if node.modifiers & ast.FUNCTION_CONST:
65f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        const = 'CONST_'
66f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return_type = 'void'
67f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if node.return_type:
68f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        # Add modifiers like 'const'.
69f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        modifiers = ''
70f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        if node.return_type.modifiers:
71f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          modifiers = ' '.join(node.return_type.modifiers) + ' '
72f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return_type = modifiers + node.return_type.name
73f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        template_args = [arg.name for arg in node.return_type.templated_types]
74f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        if template_args:
75f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          return_type += '<' + ', '.join(template_args) + '>'
76f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          if len(template_args) > 1:
77f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            for line in [
78f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                '// The following line won\'t really compile, as the return',
79f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                '// type has multiple template arguments.  To fix it, use a',
80f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                '// typedef for the return type.']:
81f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              output_lines.append(indent + line)
82f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        if node.return_type.pointer:
83f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          return_type += '*'
84f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        if node.return_type.reference:
85f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          return_type += '&'
86f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        num_parameters = len(node.parameters)
87f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        if len(node.parameters) == 1:
88f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          first_param = node.parameters[0]
89f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          if source[first_param.start:first_param.end].strip() == 'void':
90f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            # We must treat T(void) as a function with no parameters.
91f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            num_parameters = 0
92f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      tmpl = ''
93f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if class_node.templated_types:
94f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        tmpl = '_T'
95f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      mock_method_macro = 'MOCK_%sMETHOD%d%s' % (const, num_parameters, tmpl)
96f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
97f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      args = ''
98f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if node.parameters:
99f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        # Due to the parser limitations, it is impossible to keep comments
100f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        # while stripping the default parameters.  When defaults are
101f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        # present, we choose to strip them and comments (and produce
102f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        # compilable code).
103f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        # TODO(nnorwitz@google.com): Investigate whether it is possible to
104f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        # preserve parameter name when reconstructing parameter text from
105f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        # the AST.
106f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        if len([param for param in node.parameters if param.default]) > 0:
107f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          args = ', '.join(param.type.name for param in node.parameters)
108f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        else:
109f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          # Get the full text of the parameters from the start
110f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          # of the first parameter to the end of the last parameter.
111f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          start = node.parameters[0].start
112f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          end = node.parameters[-1].end
113f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          # Remove // comments.
114f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          args_strings = re.sub(r'//.*', '', source[start:end])
115f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          # Condense multiple spaces and eliminate newlines putting the
116f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          # parameters together on a single line.  Ensure there is a
117f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          # space in an argument which is split by a newline without
118f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          # intervening whitespace, e.g.: int\nBar
119f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          args = re.sub('  +', ' ', args_strings.replace('\n', ' '))
120f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
121f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      # Create the mock method definition.
122f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      output_lines.extend(['%s%s(%s,' % (indent, mock_method_macro, node.name),
123f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                           '%s%s(%s));' % (indent*3, return_type, args)])
124f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
125f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
126f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochdef _GenerateMocks(filename, source, ast_list, desired_class_names):
127f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  processed_class_names = set()
128f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  lines = []
129f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  for node in ast_list:
130f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (isinstance(node, ast.Class) and node.body and
131f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        # desired_class_names being None means that all classes are selected.
132f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        (not desired_class_names or node.name in desired_class_names)):
133f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      class_name = node.name
134f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      parent_name = class_name
135f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      processed_class_names.add(class_name)
136f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      class_node = node
137f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      # Add namespace before the class.
138f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if class_node.namespace:
139f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        lines.extend(['namespace %s {' % n for n in class_node.namespace])  # }
140f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        lines.append('')
141f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
142f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      # Add template args for templated classes.
143f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if class_node.templated_types:
144f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        # TODO(paulchang): The AST doesn't preserve template argument order,
145f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        # so we have to make up names here.
146f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        # TODO(paulchang): Handle non-type template arguments (e.g.
147f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        # template<typename T, int N>).
148f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        template_arg_count = len(class_node.templated_types.keys())
149f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        template_args = ['T%d' % n for n in range(template_arg_count)]
150f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        template_decls = ['typename ' + arg for arg in template_args]
151f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        lines.append('template <' + ', '.join(template_decls) + '>')
152f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        parent_name += '<' + ', '.join(template_args) + '>'
153f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
154f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      # Add the class prolog.
155f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      lines.append('class Mock%s : public %s {'  # }
156f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                   % (class_name, parent_name))
157f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      lines.append('%spublic:' % (' ' * (_INDENT // 2)))
158f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
159f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      # Add all the methods.
160f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      _GenerateMethods(lines, source, class_node)
161f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
162f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      # Close the class.
163f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if lines:
164f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        # If there are no virtual methods, no need for a public label.
165f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        if len(lines) == 2:
166f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          del lines[-1]
167f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
168f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        # Only close the class if there really is a class.
169f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        lines.append('};')
170f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        lines.append('')  # Add an extra newline.
171f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
172f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      # Close the namespace.
173f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if class_node.namespace:
174f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        for i in range(len(class_node.namespace)-1, -1, -1):
175f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          lines.append('}  // namespace %s' % class_node.namespace[i])
176f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        lines.append('')  # Add an extra newline.
177f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
178f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if desired_class_names:
179f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    missing_class_name_list = list(desired_class_names - processed_class_names)
180f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if missing_class_name_list:
181f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      missing_class_name_list.sort()
182f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      sys.stderr.write('Class(es) not found in %s: %s\n' %
183f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                       (filename, ', '.join(missing_class_name_list)))
184f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  elif not processed_class_names:
185f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    sys.stderr.write('No class found in %s\n' % filename)
186f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
187f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return lines
188f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
189f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
190f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochdef main(argv=sys.argv):
191f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if len(argv) < 2:
192f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    sys.stderr.write('Google Mock Class Generator v%s\n\n' %
193f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                     '.'.join(map(str, _VERSION)))
194f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    sys.stderr.write(__doc__)
195f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return 1
196f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
197f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  global _INDENT
198f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  try:
199f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    _INDENT = int(os.environ['INDENT'])
200f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  except KeyError:
201f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    pass
202f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  except:
203f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    sys.stderr.write('Unable to use indent of %s\n' % os.environ.get('INDENT'))
204f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
205f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  filename = argv[1]
206f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  desired_class_names = None  # None means all classes in the source file.
207f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if len(argv) >= 3:
208f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    desired_class_names = set(argv[2:])
209f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  source = utils.ReadFile(filename)
210f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if source is None:
211f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return 1
212f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
213f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  builder = ast.BuilderFromSource(source, filename)
214f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  try:
215f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    entire_ast = filter(None, builder.Generate())
216f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  except KeyboardInterrupt:
217f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return
218f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  except:
219f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    # An error message was already printed since we couldn't parse.
220f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    sys.exit(1)
221f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  else:
222f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    lines = _GenerateMocks(filename, source, entire_ast, desired_class_names)
223f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    sys.stdout.write('\n'.join(lines))
224f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
225f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
226f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochif __name__ == '__main__':
227f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  main(sys.argv)
228