Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / third_party / tvcm / tvcm / js_module.py
1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4 """This module contains the Module class and other classes for resources.
5
6 The Module class represents a module in the trace viewer system. A module has
7 a name, and may require a variety of other resources, such as stylesheets,
8 template objects, raw javascript, or other modules.
9
10 Other resources include HTML templates, raw javascript files, and stylesheets.
11 """
12
13 import os
14 import re
15
16 from tvcm import module
17 from tvcm import strip_js_comments
18
19 class JSModule(module.Module):
20   def Parse(self):
21     stripped_text = strip_js_comments.strip_js_comments(self.contents)
22     if self.name != 'tvcm':
23       if not IsJSModule(stripped_text):
24         raise module.DepsException('%s is not a JS Module' % self.name)
25     ValidateUsesStrictMode(self.name, stripped_text)
26     if self.name.endswith('_test'):
27       ValidateTestSuiteDefinition(self.name, stripped_text)
28     self.dependency_metadata = Parse(self.name, stripped_text)
29
30 def IsJSModule(text, text_is_stripped=True):
31   if text_is_stripped:
32     stripped_text = text
33   else:
34     stripped_text = strip_js_comments.strip_js_comments(text)
35   if re.search("""tvcm\s*\.\s*exportTo""",
36                stripped_text, re.DOTALL):
37     return True
38
39   if re.search("""tvcm\s*\.\s*require""",
40                stripped_text, re.DOTALL):
41     return True
42
43   if re.search("""tvcm\s*\.\s*unittest\s*\.\s*testSuite\((["'])(.+?)\\1""",
44                stripped_text, re.DOTALL):
45     return True
46
47   return False
48
49 def ValidateTestSuiteDefinition(module_name, stripped_text):
50   rest = stripped_text
51   num_matches = 0
52   while True:
53     m_ts = re.search("""tvcm\s*\.\s*unittest\s*\.\s*testSuite\((["'])(.+?)\\1""",
54                      rest, re.DOTALL)
55
56     # Figure out which was first.
57     matches = [m for m in [m_ts] if m]
58     matches.sort(key=lambda x: x.start())
59     if len(matches):
60       m = matches[0]
61     else:
62       break
63
64     suite_name = m.group(2)
65     if suite_name != module_name:
66       raise Exception(('%s must use the module name in its testSuite ' +
67                       'definition instead of %s') % (module_name, suite_name))
68     num_matches += 1
69     rest = rest[m.end():]
70
71   if num_matches == 0:
72       raise Exception("""Expected js module %s to contain a ' +
73           'tvcm.unittest.testSuite('%s', ...)""" % (
74           module_name, module_name))
75   if num_matches > 1:
76       raise Exception("""Must only have one tvcm.unittest.testSuite('%s', ...)""" % module_name)
77
78
79 def ValidateUsesStrictMode(module_name, stripped_text):
80   """Check that the first non-empty line is 'use strict';.
81
82   Args:
83     stripped_text: Javascript source code with comments stripped out.
84
85   Raises:
86     DepsException: This file doesn't use strict mode.
87   """
88   lines = stripped_text.split('\n')
89   for line in lines:
90     line = line.strip()
91     if len(line.strip()) == 0:
92       continue
93     if """'use strict';""" in line.strip():
94       break
95     raise module.DepsException('%s must use strict mode' % module_name)
96
97
98 def Parse(module_name, stripped_text):
99   """Parses the tvcm.require* lines in the module and returns module.ModuleDependencyMetadata.
100
101   Args:
102     stripped_text: Javascript source code with comments stripped out.
103
104   Raises:
105     DepsException: The name of a resource was not formatted properly.
106   """
107   res = module.ModuleDependencyMetadata()
108   if not module_name:
109     raise Exception("Module.name must be set.")
110
111   rest = stripped_text
112   while True:
113     # Search for require statements in the rest of the file.
114     m_r = re.search("""tvcm\s*\.\s*require\((["'])(.+?)\\1\)""",
115                     rest, re.DOTALL)
116     m_s = re.search("""tvcm\s*\.\s*requireStylesheet\((["'])(.+?)\\1\)""",
117                     rest, re.DOTALL)
118     m_t = re.search("""tvcm\s*\.\s*requireTemplate\((["'])(.+?)\\1\)""",
119                     rest, re.DOTALL)
120     m_irs = re.search("""tvcm\s*\.\s*requireRawScript\((["'])(.+?)\\1\)""",
121                     rest, re.DOTALL)
122     matches = [m for m in [m_r, m_s, m_t, m_irs] if m]
123
124     # Figure out which was first.
125     matches.sort(key=lambda x: x.start())
126     if len(matches):
127       m = matches[0]
128     else:
129       break
130
131     if m == m_r:
132       dependent_module_name = m.group(2)
133       if '/' in dependent_module_name:
134         raise module.DepsException('Slashes are not allowed in module names. '
135                                    "Use '.' instead: %s" % dependent_module_name)
136       if dependent_module_name.endswith('js'):
137         raise module.DepsException("module names shouldn't end with .js"
138                                    'The module system will append that for you: %s' %
139                                    dependent_module_name)
140       res.dependent_module_names.append(dependent_module_name)
141     elif m == m_s:
142       style_sheet_name = m.group(2)
143       if '/' in style_sheet_name:
144         raise module.DepsException('Slashes are not allowed in style sheet names. '
145                                    "Use '.' instead: %s" % style_sheet_name)
146       if style_sheet_name.endswith('.css'):
147         raise module.DepsException('Style sheets should not end in .css. '
148                                   'The module system will append that for you: %s' %
149                                   style_sheet_name)
150       res.style_sheet_names.append(style_sheet_name)
151     elif m == m_t:
152       html_template_name = m.group(2)
153       if '/' in html_template_name:
154         raise module.DepsException('Slashes are not allowed in html template names. '
155                                    "Use '.' instead: %s" % html_template_name)
156       if html_template_name.endswith('.html'):
157         raise module.DepsException(
158             'HTML templates resource names should not include extension. '
159             'The module system will append that for you.' %
160             html_template_name)
161       res.html_template_names.append(html_template_name)
162     elif m == m_irs:
163       name = m.group(2)
164       res.dependent_raw_script_relative_paths.append(name)
165
166     rest = rest[m.end():]
167
168   return res