4 # Permission is hereby granted, free of charge, to any person obtaining
5 # a copy of this software and associated documentation files (the
6 # "Software"), to deal in the Software without restriction, including
7 # without limitation the rights to use, copy, modify, merge, publish,
8 # distribute, sublicense, and/or sell copies of the Software, and to
9 # permit persons to whom the Software is furnished to do so, subject to
10 # the following conditions:
12 # The above copyright notice and this permission notice shall be included
13 # in all copies or substantial portions of the Software.
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
16 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
30 import SCons.Tool.JavaCommon
33 # Adding trace=trace to any of the parse_jave() calls below will cause
34 # the parser to spit out trace messages of the tokens it sees and the
35 # attendant transitions.
37 def trace(token, newstate):
38 from SCons.Debug import Trace
39 statename = newstate.__class__.__name__
40 Trace('token = %s, state = %s\n' % (repr(token), statename))
42 class parse_javaTestCase(unittest.TestCase):
44 def test_bare_bones(self):
45 """Test a bare-bones class"""
53 public static void main(String[] args)
56 /* This tests a former bug where strings would eat later code. */
57 String hello1 = new String("Hello, world!");
63 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input)
64 assert pkg_dir == os.path.join('com', 'sub', 'bar'), pkg_dir
65 assert classes == ['Foo'], classes
69 def test_dollar_sign(self):
70 """Test class names with $ in them"""
74 public void new$rand () {}
77 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input)
78 assert pkg_dir is None, pkg_dir
79 assert classes == ['BadDep'], classes
83 def test_inner_classes(self):
84 """Test parsing various forms of inner classes"""
91 public void execute();
96 Test implements Listener {
100 public void execute() {
101 System.out.println("In Inner");
105 String s1 = "class A";
106 String s2 = "new Listener() { }";
108 /* new Listener() { } */
112 Inner2() { Listener l = new Listener(); }
115 /* Make sure this class doesn't get interpreted as an inner class of the previous one, when "new" is used in the previous class. */
120 public static void main(String[] args) {
126 public void execute() {
127 use(new Listener( ) {
128 public void execute() {
129 System.out.println("Inside execute()");
138 void use(Listener l) {
146 public void execute() {
153 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.4')
154 assert pkg_dir is None, pkg_dir
168 assert classes == expect, classes
170 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.5')
171 assert pkg_dir is None, pkg_dir
185 assert classes == expect, (expect, classes)
187 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '5')
188 assert pkg_dir is None, pkg_dir
202 assert classes == expect, (expect, classes)
206 def test_comments(self):
207 """Test a class with comments"""
212 import java.rmi.Naming;
213 import java.rmi.RemoteException;
214 import java.rmi.RMISecurityManager;
215 import java.rmi.server.UnicastRemoteObject;
217 public class Example1 extends UnicastRemoteObject implements Hello {
219 public Example1() throws RemoteException {
223 public String sayHello() {
224 return "Hello World!";
227 public static void main(String args[]) {
228 if (System.getSecurityManager() == null) {
229 System.setSecurityManager(new RMISecurityManager());
233 Example1 obj = new Example1();
235 Naming.rebind("//myhost/HelloServer", obj);
237 System.out.println("HelloServer bound in registry");
238 } catch (Exception e) {
239 System.out.println("Example1 err: " + e.getMessage());
246 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input)
247 assert pkg_dir == os.path.join('com', 'sub', 'foo'), pkg_dir
248 assert classes == ['Example1'], classes
251 def test_arrays(self):
252 """Test arrays of class instances"""
256 MyClass abc = new MyClass();
257 MyClass xyz = new MyClass();
258 MyClass _array[] = new MyClass[] {
265 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input)
266 assert pkg_dir is None, pkg_dir
267 assert classes == ['Test'], classes
271 def test_backslash(self):
272 """Test backslash handling"""
277 private class MyInternal
280 private final static String PATH = "images\\\\";
284 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input)
285 assert pkg_dir is None, pkg_dir
286 assert classes == ['MyTabs$MyInternal', 'MyTabs'], classes
290 """Test the Java 1.5 enum keyword"""
297 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input)
298 assert pkg_dir == 'p', pkg_dir
299 assert classes == ['a'], classes
302 def test_anon_classes(self):
303 """Test anonymous classes"""
306 public abstract class TestClass
308 public void completed()
321 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input)
322 assert pkg_dir is None, pkg_dir
323 assert classes == ['TestClass$1', 'TestClass$2', 'TestClass'], classes
326 def test_closing_bracket(self):
327 """Test finding a closing bracket instead of an anonymous class"""
331 public static void main(String[] args) {
332 Foo[] fooArray = new Foo[] { new Foo() };
339 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input)
340 assert pkg_dir is None, pkg_dir
341 assert classes == ['TestSCons', 'Foo'], classes
344 def test_dot_class_attributes(self):
345 """Test handling ".class" attributes"""
348 public class Test extends Object
351 Class c = Object[].class;
352 Object[] s = new Object[] {};
357 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input)
358 assert classes == ['Test'], classes
363 public void F(Object[] o) {
364 F(new Object[] {Object[].class});
366 public void G(Object[] o) {
373 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input)
374 assert pkg_dir is None, pkg_dir
375 assert classes == ['A$B', 'A'], classes
377 def test_anonymous_classes_with_parentheses(self):
378 """Test finding anonymous classes marked by parentheses"""
384 public static void main(String[] args) {
387 public String toString() {
392 public String toString() {
400 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.4')
401 assert classes == ['Foo$1', 'Foo$2', 'Foo'], classes
403 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.5')
404 assert classes == ['Foo$1', 'Foo$1$1', 'Foo'], classes
406 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '6')
407 assert classes == ['Foo$1', 'Foo$1$1', 'Foo'], classes
411 def test_nested_anonymous_inner_classes(self):
412 """Test finding nested anonymous inner classes"""
415 // import java.util.*;
417 public class NestedExample
419 public NestedExample()
421 Thread t = new Thread() {
424 Thread t = new Thread() {
427 try {Thread.sleep(200);}
428 catch (Exception e) {}
433 try {Thread.sleep(200);}
434 catch (Exception e) {}
441 public static void main(String argv[])
443 NestedExample e = new NestedExample();
448 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.4')
449 expect = [ 'NestedExample$1', 'NestedExample$2', 'NestedExample' ]
450 assert expect == classes, (expect, classes)
452 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.5')
453 expect = [ 'NestedExample$1', 'NestedExample$1$1', 'NestedExample' ]
454 assert expect == classes, (expect, classes)
456 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '6')
457 expect = [ 'NestedExample$1', 'NestedExample$1$1', 'NestedExample' ]
458 assert expect == classes, (expect, classes)
460 def test_private_inner_class_instantiation(self):
461 """Test anonymous inner class generated by private instantiation"""
479 # This is what we *should* generate, apparently due to the
480 # private instantiation of the inner class, but don't today.
481 #expect = [ 'test$1', 'test$inner', 'test' ]
483 # What our parser currently generates, which doesn't match
484 # what the Java compiler actually generates.
485 expect = [ 'test$inner', 'test' ]
487 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.4')
488 assert expect == classes, (expect, classes)
490 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.5')
491 assert expect == classes, (expect, classes)
493 def test_floating_point_numbers(self):
494 """Test floating-point numbers in the input stream"""
502 Object anonymousInnerOK = new Runnable() { public void run () {} };
507 class InnerOK { InnerOK () { } }
510 System.out.println("a number: " + 1000.0 + "");
516 Object anonymousInnerBAD = new Runnable() { public void run () {} };
521 class InnerBAD { InnerBAD () { } }
525 expect = ['Broken$1', 'Broken$InnerOK', 'Broken$2', 'Broken$InnerBAD', 'Broken']
527 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.4')
528 assert expect == classes, (expect, classes)
530 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.5')
531 assert expect == classes, (expect, classes)
534 def test_genercis(self):
535 """Test that generics don't interfere with detecting anonymous classes"""
538 import java.util.Date;
539 import java.util.Comparator;
545 Comparator<Date> comp = new Comparator<Date>()
547 static final long serialVersionUID = 1L;
548 public int compare(Date lhs, Date rhs)
557 expect = [ 'Foo$1', 'Foo' ]
559 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.6')
560 assert expect == classes, (expect, classes)
562 pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '6')
563 assert expect == classes, (expect, classes)
567 if __name__ == "__main__":
568 suite = unittest.TestSuite()
569 tclasses = [ parse_javaTestCase ]
570 for tclass in tclasses:
571 names = unittest.getTestCaseNames(tclass, 'test_')
572 suite.addTests(list(map(tclass, names)))
573 if not unittest.TextTestRunner().run(suite).wasSuccessful():
578 # indent-tabs-mode:nil
580 # vim: set expandtab tabstop=4 shiftwidth=4: