Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Extracts native methods from a Java file and generates the JNI bindings. | 6 """Extracts native methods from a Java file and generates the JNI bindings. |
| 7 If you change this, please run and update the tests.""" | 7 If you change this, please run and update the tests.""" |
| 8 | 8 |
| 9 import collections | 9 import collections |
| 10 import errno | 10 import errno |
| (...skipping 563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 574 stderr=subprocess.PIPE) | 574 stderr=subprocess.PIPE) |
| 575 stdout, _ = p.communicate() | 575 stdout, _ = p.communicate() |
| 576 jni_from_javap = JNIFromJavaP(stdout.split('\n'), options) | 576 jni_from_javap = JNIFromJavaP(stdout.split('\n'), options) |
| 577 return jni_from_javap | 577 return jni_from_javap |
| 578 | 578 |
| 579 | 579 |
| 580 class JNIFromJavaSource(object): | 580 class JNIFromJavaSource(object): |
| 581 """Uses the given java source file to generate the JNI header file.""" | 581 """Uses the given java source file to generate the JNI header file.""" |
| 582 | 582 |
| 583 def __init__(self, contents, fully_qualified_class, options): | 583 def __init__(self, contents, fully_qualified_class, options): |
| 584 contents = self._RemoveComments(contents, options) | 584 contents = self._RemoveComments(contents) |
| 585 JniParams.SetFullyQualifiedClass(fully_qualified_class) | 585 JniParams.SetFullyQualifiedClass(fully_qualified_class) |
| 586 JniParams.ExtractImportsAndInnerClasses(contents) | 586 JniParams.ExtractImportsAndInnerClasses(contents) |
| 587 jni_namespace = ExtractJNINamespace(contents) or options.namespace | 587 jni_namespace = ExtractJNINamespace(contents) or options.namespace |
| 588 natives = ExtractNatives(contents, options.ptr_type) | 588 natives = ExtractNatives(contents, options.ptr_type) |
| 589 called_by_natives = ExtractCalledByNatives(contents) | 589 called_by_natives = ExtractCalledByNatives(contents) |
| 590 if len(natives) == 0 and len(called_by_natives) == 0: | 590 if len(natives) == 0 and len(called_by_natives) == 0: |
| 591 raise SyntaxError('Unable to find any JNI methods for %s.' % | 591 raise SyntaxError('Unable to find any JNI methods for %s.' % |
| 592 fully_qualified_class) | 592 fully_qualified_class) |
| 593 inl_header_file_generator = InlHeaderFileGenerator( | 593 inl_header_file_generator = InlHeaderFileGenerator( |
| 594 jni_namespace, fully_qualified_class, natives, called_by_natives, | 594 jni_namespace, fully_qualified_class, natives, called_by_natives, |
| 595 [], options) | 595 [], options) |
| 596 self.content = inl_header_file_generator.GetContent() | 596 self.content = inl_header_file_generator.GetContent() |
| 597 | 597 |
| 598 def _RemoveComments(self, contents, options): | 598 # Match single line comments, multiline comments, character literals, and |
| 599 # double-quoted strings. | |
| 600 _comment_remover_regex = re.compile( | |
|
bulach
2014/04/14 11:30:44
nit: maybe move this before __init__ ? it took me
Torne
2014/04/14 11:41:06
Done.
| |
| 601 r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', | |
| 602 re.DOTALL | re.MULTILINE) | |
| 603 | |
| 604 def _RemoveComments(self, contents): | |
|
bulach
2014/04/14 11:30:44
...and then perhaps make this @staticmethod?
Torne
2014/04/14 11:41:06
Static methods can't access members of the class,
| |
| 599 # We need to support both inline and block comments, and we need to handle | 605 # We need to support both inline and block comments, and we need to handle |
| 600 # strings that contain '//' or '/*'. Rather than trying to do all that with | 606 # strings that contain '//' or '/*'. |
| 601 # regexps, we just pipe the contents through the C preprocessor. We tell cpp | 607 # TODO(bulach): This is a bit hacky. It would be cleaner to use a real Java |
| 602 # the file has already been preprocessed, so it just removes comments and | |
| 603 # doesn't try to parse #include, #pragma etc. | |
| 604 # | |
| 605 # TODO(husky): This is a bit hacky. It would be cleaner to use a real Java | |
| 606 # parser. Maybe we could ditch JNIFromJavaSource and just always use | 608 # parser. Maybe we could ditch JNIFromJavaSource and just always use |
| 607 # JNIFromJavaP; or maybe we could rewrite this script in Java and use APT. | 609 # JNIFromJavaP; or maybe we could rewrite this script in Java and use APT. |
| 608 # http://code.google.com/p/chromium/issues/detail?id=138941 | 610 # http://code.google.com/p/chromium/issues/detail?id=138941 |
| 609 p = subprocess.Popen(args=[options.cpp, '-fpreprocessed'], | 611 def replacer(match): |
| 610 stdin=subprocess.PIPE, | 612 # Replace matches that are comments with nothing; return literals/strings |
| 611 stdout=subprocess.PIPE, | 613 # unchanged. |
| 612 stderr=subprocess.PIPE) | 614 s = match.group(0) |
| 613 stdout, _ = p.communicate(contents) | 615 if s.startswith('/'): |
| 614 return stdout | 616 return "" |
|
bulach
2014/04/14 11:30:44
nit: s/""/''/
Torne
2014/04/14 11:41:06
Done.
| |
| 617 else: | |
| 618 return s | |
| 619 return self._comment_remover_regex.sub(replacer, contents) | |
| 615 | 620 |
| 616 def GetContent(self): | 621 def GetContent(self): |
| 617 return self.content | 622 return self.content |
| 618 | 623 |
| 619 @staticmethod | 624 @staticmethod |
| 620 def CreateFromFile(java_file_name, options): | 625 def CreateFromFile(java_file_name, options): |
| 621 contents = file(java_file_name).read() | 626 contents = file(java_file_name).read() |
| 622 fully_qualified_class = ExtractFullyQualifiedJavaClassName(java_file_name, | 627 fully_qualified_class = ExtractFullyQualifiedJavaClassName(java_file_name, |
| 623 contents) | 628 contents) |
| 624 return JNIFromJavaSource(contents, fully_qualified_class, options) | 629 return JNIFromJavaSource(contents, fully_qualified_class, options) |
| (...skipping 712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1337 root_name = os.path.splitext(os.path.basename(input_file))[0] | 1342 root_name = os.path.splitext(os.path.basename(input_file))[0] |
| 1338 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' | 1343 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' |
| 1339 if options.jarjar: | 1344 if options.jarjar: |
| 1340 with open(options.jarjar) as f: | 1345 with open(options.jarjar) as f: |
| 1341 JniParams.SetJarJarMappings(f.read()) | 1346 JniParams.SetJarJarMappings(f.read()) |
| 1342 GenerateJNIHeader(input_file, output_file, options) | 1347 GenerateJNIHeader(input_file, output_file, options) |
| 1343 | 1348 |
| 1344 | 1349 |
| 1345 if __name__ == '__main__': | 1350 if __name__ == '__main__': |
| 1346 sys.exit(main(sys.argv)) | 1351 sys.exit(main(sys.argv)) |
| OLD | NEW |