Backed out changeset 7272b7396c78 (bug 1932758) for causing fenix debug failures...
[gecko.git] / dom / canvas / test / webgl-conf / checkout / closure-library / closure / bin / build / source.py
blobbe5e0d8ad64e08d968a9b6fcd5c37ad7da9ffbd6
1 # Copyright 2009 The Closure Library Authors. All Rights Reserved.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS-IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
16 """Scans a source JS file for its provided and required namespaces.
18 Simple class to scan a JavaScript file and express its dependencies.
19 """
21 __author__ = 'nnaze@google.com'
24 import re
26 _BASE_REGEX_STRING = r'^\s*goog\.%s\(\s*[\'"](.+)[\'"]\s*\)'
27 _MODULE_REGEX = re.compile(_BASE_REGEX_STRING % 'module')
28 _PROVIDE_REGEX = re.compile(_BASE_REGEX_STRING % 'provide')
30 _REQUIRE_REGEX_STRING = (r'^\s*(?:(?:var|let|const)\s+[a-zA-Z_$][a-zA-Z0-9$_]*'
31 r'\s*=\s*)?goog\.require\(\s*[\'"](.+)[\'"]\s*\)')
32 _REQUIRES_REGEX = re.compile(_REQUIRE_REGEX_STRING)
35 class Source(object):
36 """Scans a JavaScript source for its provided and required namespaces."""
38 # Matches a "/* ... */" comment.
39 # Note: We can't definitively distinguish a "/*" in a string literal without a
40 # state machine tokenizer. We'll assume that a line starting with whitespace
41 # and "/*" is a comment.
42 _COMMENT_REGEX = re.compile(
43 r"""
44 ^\s* # Start of a new line and whitespace
45 /\* # Opening "/*"
46 .*? # Non greedy match of any characters (including newlines)
47 \*/ # Closing "*/""",
48 re.MULTILINE | re.DOTALL | re.VERBOSE)
50 def __init__(self, source):
51 """Initialize a source.
53 Args:
54 source: str, The JavaScript source.
55 """
57 self.provides = set()
58 self.requires = set()
59 self.is_goog_module = False
61 self._source = source
62 self._ScanSource()
64 def GetSource(self):
65 """Get the source as a string."""
66 return self._source
68 @classmethod
69 def _StripComments(cls, source):
70 return cls._COMMENT_REGEX.sub('', source)
72 @classmethod
73 def _HasProvideGoogFlag(cls, source):
74 """Determines whether the @provideGoog flag is in a comment."""
75 for comment_content in cls._COMMENT_REGEX.findall(source):
76 if '@provideGoog' in comment_content:
77 return True
79 return False
81 def _ScanSource(self):
82 """Fill in provides and requires by scanning the source."""
84 stripped_source = self._StripComments(self.GetSource())
86 source_lines = stripped_source.splitlines()
87 for line in source_lines:
88 match = _PROVIDE_REGEX.match(line)
89 if match:
90 self.provides.add(match.group(1))
91 match = _MODULE_REGEX.match(line)
92 if match:
93 self.provides.add(match.group(1))
94 self.is_goog_module = True
95 match = _REQUIRES_REGEX.match(line)
96 if match:
97 self.requires.add(match.group(1))
99 # Closure's base file implicitly provides 'goog'.
100 # This is indicated with the @provideGoog flag.
101 if self._HasProvideGoogFlag(self.GetSource()):
103 if len(self.provides) or len(self.requires):
104 raise Exception(
105 'Base file should not provide or require namespaces.')
107 self.provides.add('goog')
110 def GetFileContents(path):
111 """Get a file's contents as a string.
113 Args:
114 path: str, Path to file.
116 Returns:
117 str, Contents of file.
119 Raises:
120 IOError: An error occurred opening or reading the file.
123 fileobj = open(path)
124 try:
125 return fileobj.read()
126 finally:
127 fileobj.close()