1cb93a386Sopenharmony_ci'''
2cb93a386Sopenharmony_ciCopyright 2011 Google Inc.
3cb93a386Sopenharmony_ci
4cb93a386Sopenharmony_ciUse of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_cifound in the LICENSE file.
6cb93a386Sopenharmony_ci'''
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ciimport datetime
9cb93a386Sopenharmony_ciimport re
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_cidef CreateParser(filepath):
12cb93a386Sopenharmony_ci    """Returns a Parser as appropriate for the file at this filepath.
13cb93a386Sopenharmony_ci    """
14cb93a386Sopenharmony_ci    if (filepath.endswith('.cpp') or
15cb93a386Sopenharmony_ci        filepath.endswith('.h') or
16cb93a386Sopenharmony_ci        filepath.endswith('.c')):
17cb93a386Sopenharmony_ci        return CParser()
18cb93a386Sopenharmony_ci    else:
19cb93a386Sopenharmony_ci        return None
20cb93a386Sopenharmony_ci
21cb93a386Sopenharmony_ci
22cb93a386Sopenharmony_ciclass Parser(object):
23cb93a386Sopenharmony_ci    """Base class for all language-specific parsers.
24cb93a386Sopenharmony_ci    """
25cb93a386Sopenharmony_ci
26cb93a386Sopenharmony_ci    def __init__(self):
27cb93a386Sopenharmony_ci        self._copyright_pattern = re.compile('copyright', re.IGNORECASE)
28cb93a386Sopenharmony_ci        self._attribute_pattern = re.compile(
29cb93a386Sopenharmony_ci            'copyright.*\D(\d{4})\W*(\w.*[\w.])', re.IGNORECASE)
30cb93a386Sopenharmony_ci
31cb93a386Sopenharmony_ci    def FindCopyrightBlock(self, comment_blocks):
32cb93a386Sopenharmony_ci        """Given a list of comment block strings, return the one that seems
33cb93a386Sopenharmony_ci        like the most likely copyright block.
34cb93a386Sopenharmony_ci
35cb93a386Sopenharmony_ci        Returns None if comment_blocks was empty, or if we couldn't find
36cb93a386Sopenharmony_ci        a comment block that contains copyright info."""
37cb93a386Sopenharmony_ci        if not comment_blocks:
38cb93a386Sopenharmony_ci            return None
39cb93a386Sopenharmony_ci        for block in comment_blocks:
40cb93a386Sopenharmony_ci            if self._copyright_pattern.search(block):
41cb93a386Sopenharmony_ci                return block
42cb93a386Sopenharmony_ci
43cb93a386Sopenharmony_ci    def GetCopyrightBlockAttributes(self, comment_block):
44cb93a386Sopenharmony_ci        """Given a comment block, return a tuple of attributes: (year, holder).
45cb93a386Sopenharmony_ci
46cb93a386Sopenharmony_ci        If comment_block is None, or none of the attributes are found,
47cb93a386Sopenharmony_ci        this will return (None, None)."""
48cb93a386Sopenharmony_ci        if not comment_block:
49cb93a386Sopenharmony_ci            return (None, None)
50cb93a386Sopenharmony_ci        matches = self._attribute_pattern.findall(comment_block)
51cb93a386Sopenharmony_ci        if not matches:
52cb93a386Sopenharmony_ci            return (None, None)
53cb93a386Sopenharmony_ci        first_match = matches[0]
54cb93a386Sopenharmony_ci        return (first_match[0], first_match[1])
55cb93a386Sopenharmony_ci
56cb93a386Sopenharmony_ci
57cb93a386Sopenharmony_ciclass CParser(Parser):
58cb93a386Sopenharmony_ci    """Parser that knows how to parse C/C++ files.
59cb93a386Sopenharmony_ci    """
60cb93a386Sopenharmony_ci
61cb93a386Sopenharmony_ci    DEFAULT_YEAR = datetime.date.today().year
62cb93a386Sopenharmony_ci    DEFAULT_HOLDER = 'Google Inc.'
63cb93a386Sopenharmony_ci    COPYRIGHT_BLOCK_FORMAT = '''
64cb93a386Sopenharmony_ci/*
65cb93a386Sopenharmony_ci * Copyright %s %s
66cb93a386Sopenharmony_ci *
67cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
68cb93a386Sopenharmony_ci * found in the LICENSE file.
69cb93a386Sopenharmony_ci */
70cb93a386Sopenharmony_ci'''
71cb93a386Sopenharmony_ci
72cb93a386Sopenharmony_ci    def __init__(self):
73cb93a386Sopenharmony_ci        super(CParser, self).__init__()
74cb93a386Sopenharmony_ci        self._comment_pattern = re.compile('/\*.*?\*/', re.DOTALL)
75cb93a386Sopenharmony_ci
76cb93a386Sopenharmony_ci    def FindAllCommentBlocks(self, file_contents):
77cb93a386Sopenharmony_ci        """Returns a list of all comment blocks within these file contents.
78cb93a386Sopenharmony_ci        """
79cb93a386Sopenharmony_ci        return self._comment_pattern.findall(file_contents)
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_ci    def CreateCopyrightBlock(self, year, holder):
82cb93a386Sopenharmony_ci        """Returns a copyright block suitable for this language, with the
83cb93a386Sopenharmony_ci        given attributes.
84cb93a386Sopenharmony_ci
85cb93a386Sopenharmony_ci        @param year year in which to hold copyright (defaults to DEFAULT_YEAR)
86cb93a386Sopenharmony_ci        @param holder holder of copyright (defaults to DEFAULT_HOLDER)
87cb93a386Sopenharmony_ci        """
88cb93a386Sopenharmony_ci        if not year:
89cb93a386Sopenharmony_ci            year = self.DEFAULT_YEAR
90cb93a386Sopenharmony_ci        if not holder:
91cb93a386Sopenharmony_ci            holder = self.DEFAULT_HOLDER
92cb93a386Sopenharmony_ci        return self.COPYRIGHT_BLOCK_FORMAT % (year, holder)
93