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

Side by Side Diff: scons-2.0.1/engine/SCons/Tool/JavaCommon.py

Issue 6711079: Added an unmodified copy of SCons to third_party. (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/third_party/
Patch Set: '' Created 9 years, 9 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 unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 """SCons.Tool.JavaCommon
2
3 Stuff for processing Java.
4
5 """
6
7 #
8 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 The S Cons Foundation
9 #
10 # Permission is hereby granted, free of charge, to any person obtaining
11 # a copy of this software and associated documentation files (the
12 # "Software"), to deal in the Software without restriction, including
13 # without limitation the rights to use, copy, modify, merge, publish,
14 # distribute, sublicense, and/or sell copies of the Software, and to
15 # permit persons to whom the Software is furnished to do so, subject to
16 # the following conditions:
17 #
18 # The above copyright notice and this permission notice shall be included
19 # in all copies or substantial portions of the Software.
20 #
21 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
22 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
23 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #
29
30 __revision__ = "src/engine/SCons/Tool/JavaCommon.py 5134 2010/08/16 23:02:40 bde egan"
31
32 import os
33 import os.path
34 import re
35
36 java_parsing = 1
37
38 default_java_version = '1.4'
39
40 if java_parsing:
41 # Parse Java files for class names.
42 #
43 # This is a really cool parser from Charles Crain
44 # that finds appropriate class names in Java source.
45
46 # A regular expression that will find, in a java file:
47 # newlines;
48 # double-backslashes;
49 # a single-line comment "//";
50 # single or double quotes preceeded by a backslash;
51 # single quotes, double quotes, open or close braces, semi-colons,
52 # periods, open or close parentheses;
53 # floating-point numbers;
54 # any alphanumeric token (keyword, class name, specifier);
55 # any alphanumeric token surrounded by angle brackets (generics);
56 # the multi-line comment begin and end tokens /* and */;
57 # array declarations "[]".
58 _reToken = re.compile(r'(\n|\\\\|//|\\[\'"]|[\'"\{\}\;\.\(\)]|' +
59 r'\d*\.\d*|[A-Za-z_][\w\$\.]*|<[A-Za-z_]\w+>|' +
60 r'/\*|\*/|\[\])')
61
62 class OuterState(object):
63 """The initial state for parsing a Java file for classes,
64 interfaces, and anonymous inner classes."""
65 def __init__(self, version=default_java_version):
66
67 if not version in ('1.1', '1.2', '1.3','1.4', '1.5', '1.6',
68 '5', '6'):
69 msg = "Java version %s not supported" % version
70 raise NotImplementedError(msg)
71
72 self.version = version
73 self.listClasses = []
74 self.listOutputs = []
75 self.stackBrackets = []
76 self.brackets = 0
77 self.nextAnon = 1
78 self.localClasses = []
79 self.stackAnonClassBrackets = []
80 self.anonStacksStack = [[0]]
81 self.package = None
82
83 def trace(self):
84 pass
85
86 def __getClassState(self):
87 try:
88 return self.classState
89 except AttributeError:
90 ret = ClassState(self)
91 self.classState = ret
92 return ret
93
94 def __getPackageState(self):
95 try:
96 return self.packageState
97 except AttributeError:
98 ret = PackageState(self)
99 self.packageState = ret
100 return ret
101
102 def __getAnonClassState(self):
103 try:
104 return self.anonState
105 except AttributeError:
106 self.outer_state = self
107 ret = SkipState(1, AnonClassState(self))
108 self.anonState = ret
109 return ret
110
111 def __getSkipState(self):
112 try:
113 return self.skipState
114 except AttributeError:
115 ret = SkipState(1, self)
116 self.skipState = ret
117 return ret
118
119 def __getAnonStack(self):
120 return self.anonStacksStack[-1]
121
122 def openBracket(self):
123 self.brackets = self.brackets + 1
124
125 def closeBracket(self):
126 self.brackets = self.brackets - 1
127 if len(self.stackBrackets) and \
128 self.brackets == self.stackBrackets[-1]:
129 self.listOutputs.append('$'.join(self.listClasses))
130 self.localClasses.pop()
131 self.listClasses.pop()
132 self.anonStacksStack.pop()
133 self.stackBrackets.pop()
134 if len(self.stackAnonClassBrackets) and \
135 self.brackets == self.stackAnonClassBrackets[-1]:
136 self.__getAnonStack().pop()
137 self.stackAnonClassBrackets.pop()
138
139 def parseToken(self, token):
140 if token[:2] == '//':
141 return IgnoreState('\n', self)
142 elif token == '/*':
143 return IgnoreState('*/', self)
144 elif token == '{':
145 self.openBracket()
146 elif token == '}':
147 self.closeBracket()
148 elif token in [ '"', "'" ]:
149 return IgnoreState(token, self)
150 elif token == "new":
151 # anonymous inner class
152 if len(self.listClasses) > 0:
153 return self.__getAnonClassState()
154 return self.__getSkipState() # Skip the class name
155 elif token in ['class', 'interface', 'enum']:
156 if len(self.listClasses) == 0:
157 self.nextAnon = 1
158 self.stackBrackets.append(self.brackets)
159 return self.__getClassState()
160 elif token == 'package':
161 return self.__getPackageState()
162 elif token == '.':
163 # Skip the attribute, it might be named "class", in which
164 # case we don't want to treat the following token as
165 # an inner class name...
166 return self.__getSkipState()
167 return self
168
169 def addAnonClass(self):
170 """Add an anonymous inner class"""
171 if self.version in ('1.1', '1.2', '1.3', '1.4'):
172 clazz = self.listClasses[0]
173 self.listOutputs.append('%s$%d' % (clazz, self.nextAnon))
174 elif self.version in ('1.5', '1.6', '5', '6'):
175 self.stackAnonClassBrackets.append(self.brackets)
176 className = []
177 className.extend(self.listClasses)
178 self.__getAnonStack()[-1] = self.__getAnonStack()[-1] + 1
179 for anon in self.__getAnonStack():
180 className.append(str(anon))
181 self.listOutputs.append('$'.join(className))
182
183 self.nextAnon = self.nextAnon + 1
184 self.__getAnonStack().append(0)
185
186 def setPackage(self, package):
187 self.package = package
188
189 class AnonClassState(object):
190 """A state that looks for anonymous inner classes."""
191 def __init__(self, old_state):
192 # outer_state is always an instance of OuterState
193 self.outer_state = old_state.outer_state
194 self.old_state = old_state
195 self.brace_level = 0
196 def parseToken(self, token):
197 # This is an anonymous class if and only if the next
198 # non-whitespace token is a bracket. Everything between
199 # braces should be parsed as normal java code.
200 if token[:2] == '//':
201 return IgnoreState('\n', self)
202 elif token == '/*':
203 return IgnoreState('*/', self)
204 elif token == '\n':
205 return self
206 elif token[0] == '<' and token[-1] == '>':
207 return self
208 elif token == '(':
209 self.brace_level = self.brace_level + 1
210 return self
211 if self.brace_level > 0:
212 if token == 'new':
213 # look further for anonymous inner class
214 return SkipState(1, AnonClassState(self))
215 elif token in [ '"', "'" ]:
216 return IgnoreState(token, self)
217 elif token == ')':
218 self.brace_level = self.brace_level - 1
219 return self
220 if token == '{':
221 self.outer_state.addAnonClass()
222 return self.old_state.parseToken(token)
223
224 class SkipState(object):
225 """A state that will skip a specified number of tokens before
226 reverting to the previous state."""
227 def __init__(self, tokens_to_skip, old_state):
228 self.tokens_to_skip = tokens_to_skip
229 self.old_state = old_state
230 def parseToken(self, token):
231 self.tokens_to_skip = self.tokens_to_skip - 1
232 if self.tokens_to_skip < 1:
233 return self.old_state
234 return self
235
236 class ClassState(object):
237 """A state we go into when we hit a class or interface keyword."""
238 def __init__(self, outer_state):
239 # outer_state is always an instance of OuterState
240 self.outer_state = outer_state
241 def parseToken(self, token):
242 # the next non-whitespace token should be the name of the class
243 if token == '\n':
244 return self
245 # If that's an inner class which is declared in a method, it
246 # requires an index prepended to the class-name, e.g.
247 # 'Foo$1Inner' (Tigris Issue 2087)
248 if self.outer_state.localClasses and \
249 self.outer_state.stackBrackets[-1] > \
250 self.outer_state.stackBrackets[-2]+1:
251 locals = self.outer_state.localClasses[-1]
252 try:
253 idx = locals[token]
254 locals[token] = locals[token]+1
255 except KeyError:
256 locals[token] = 1
257 token = str(locals[token]) + token
258 self.outer_state.localClasses.append({})
259 self.outer_state.listClasses.append(token)
260 self.outer_state.anonStacksStack.append([0])
261 return self.outer_state
262
263 class IgnoreState(object):
264 """A state that will ignore all tokens until it gets to a
265 specified token."""
266 def __init__(self, ignore_until, old_state):
267 self.ignore_until = ignore_until
268 self.old_state = old_state
269 def parseToken(self, token):
270 if self.ignore_until == token:
271 return self.old_state
272 return self
273
274 class PackageState(object):
275 """The state we enter when we encounter the package keyword.
276 We assume the next token will be the package name."""
277 def __init__(self, outer_state):
278 # outer_state is always an instance of OuterState
279 self.outer_state = outer_state
280 def parseToken(self, token):
281 self.outer_state.setPackage(token)
282 return self.outer_state
283
284 def parse_java_file(fn, version=default_java_version):
285 return parse_java(open(fn, 'r').read(), version)
286
287 def parse_java(contents, version=default_java_version, trace=None):
288 """Parse a .java file and return a double of package directory,
289 plus a list of .class files that compiling that .java file will
290 produce"""
291 package = None
292 initial = OuterState(version)
293 currstate = initial
294 for token in _reToken.findall(contents):
295 # The regex produces a bunch of groups, but only one will
296 # have anything in it.
297 currstate = currstate.parseToken(token)
298 if trace: trace(token, currstate)
299 if initial.package:
300 package = initial.package.replace('.', os.sep)
301 return (package, initial.listOutputs)
302
303 else:
304 # Don't actually parse Java files for class names.
305 #
306 # We might make this a configurable option in the future if
307 # Java-file parsing takes too long (although it shouldn't relative
308 # to how long the Java compiler itself seems to take...).
309
310 def parse_java_file(fn):
311 """ "Parse" a .java file.
312
313 This actually just splits the file name, so the assumption here
314 is that the file name matches the public class name, and that
315 the path to the file is the same as the package name.
316 """
317 return os.path.split(file)
318
319 # Local Variables:
320 # tab-width:4
321 # indent-tabs-mode:nil
322 # End:
323 # vim: set expandtab tabstop=4 shiftwidth=4:
OLDNEW
« no previous file with comments | « scons-2.0.1/engine/SCons/Tool/FortranCommon.py ('k') | scons-2.0.1/engine/SCons/Tool/MSCommon/__init__.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698