OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 2 # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
3 # for details. All rights reserved. Use of this source code is governed by a | 3 # for details. All rights reserved. Use of this source code is governed by a |
4 # BSD-style license that can be found in the LICENSE file. | 4 # BSD-style license that can be found in the LICENSE file. |
5 | 5 |
6 import copy | 6 import copy |
7 import database | 7 import database |
8 import logging | 8 import logging |
9 import monitored | 9 import monitored |
10 import multiprocessing | 10 import multiprocessing |
(...skipping 735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
746 def dictionary_to_map(type_node): | 746 def dictionary_to_map(type_node): |
747 if self._database.HasDictionary(type_node.id): | 747 if self._database.HasDictionary(type_node.id): |
748 type_node.dictionary = type_node.id | 748 type_node.dictionary = type_node.id |
749 type_node.id = 'Dictionary' | 749 type_node.id = 'Dictionary' |
750 | 750 |
751 def all_types(node): | 751 def all_types(node): |
752 map(dictionary_to_map, node.all(IDLType)) | 752 map(dictionary_to_map, node.all(IDLType)) |
753 | 753 |
754 for interface in self._database.GetInterfaces(): | 754 for interface in self._database.GetInterfaces(): |
755 map(all_types, interface.all(IDLExtAttrFunctionValue)) | 755 map(all_types, interface.all(IDLExtAttrFunctionValue)) |
| 756 map(all_types, interface.attributes) |
756 map(all_types, interface.operations) | 757 map(all_types, interface.operations) |
757 | 758 |
758 def fetch_constructor_data(self, options): | 759 def fetch_constructor_data(self, options): |
759 window_interface = self._database.GetInterface('Window') | 760 window_interface = self._database.GetInterface('Window') |
760 for attr in window_interface.attributes: | 761 for attr in window_interface.attributes: |
761 type = attr.type.id | 762 type = attr.type.id |
762 if not type.endswith('Constructor'): | 763 if not type.endswith('Constructor'): |
763 continue | 764 continue |
764 type = re.sub('(Constructor)+$', '', type) | 765 type = re.sub('(Constructor)+$', '', type) |
765 # TODO(antonm): Ideally we'd like to have pristine copy of WebKit IDLs and
fetch | 766 # TODO(antonm): Ideally we'd like to have pristine copy of WebKit IDLs and
fetch |
766 # this information directly from it. Unfortunately right now database is
massaged | 767 # this information directly from it. Unfortunately right now database is
massaged |
767 # a lot so it's difficult to maintain necessary information on Window itse
lf. | 768 # a lot so it's difficult to maintain necessary information on Window itse
lf. |
768 interface = self._database.GetInterface(type) | 769 interface = self._database.GetInterface(type) |
769 if 'V8EnabledPerContext' in attr.ext_attrs: | 770 if 'V8EnabledPerContext' in attr.ext_attrs: |
770 interface.ext_attrs['synthesizedV8EnabledPerContext'] = \ | 771 interface.ext_attrs['synthesizedV8EnabledPerContext'] = \ |
771 attr.ext_attrs['V8EnabledPerContext'] | 772 attr.ext_attrs['V8EnabledPerContext'] |
772 if 'V8EnabledAtRuntime' in attr.ext_attrs: | 773 if 'V8EnabledAtRuntime' in attr.ext_attrs: |
773 interface.ext_attrs['synthesizedV8EnabledAtRuntime'] = \ | 774 interface.ext_attrs['synthesizedV8EnabledAtRuntime'] = \ |
774 attr.ext_attrs['V8EnabledAtRuntime'] or attr.id | 775 attr.ext_attrs['V8EnabledAtRuntime'] or attr.id |
| 776 |
| 777 # Iterate of the database looking for relationships between dictionaries and |
| 778 # interfaces marked with NoInterfaceObject. This mechanism can be used for |
| 779 # other IDL analysis. |
| 780 def examine_database(self): |
| 781 # Contains list of dictionary structure: {'dictionary': dictionary, 'usages'
: []} |
| 782 self._diag_dictionaries = []; |
| 783 self._dictionaries_used_types = []; |
| 784 |
| 785 # Record any dictionary. |
| 786 for dictionary in self._database.GetDictionaries(): |
| 787 self._diag_dictionaries.append({'dictionary': dictionary, 'usages': []}); |
| 788 |
| 789 # Contains list of NoInterfaceObject structures: {'no_interface_object': dic
tionary, 'usages': []} |
| 790 self._diag_no_interfaces = []; |
| 791 self._no_interfaces_used_types = []; |
| 792 |
| 793 # Record any interface with Blink IDL Extended Attribute 'NoInterfaceObject'
. |
| 794 for interface in self._database.GetInterfaces(): |
| 795 if interface.is_no_interface_object: |
| 796 self._diag_no_interfaces.append({'no_interface_object': interface, 'usag
es': []}); |
| 797 |
| 798 for interface in self._database.GetInterfaces(): |
| 799 self._constructors(interface) |
| 800 self._constructors(interface, check_dictionaries=False) |
| 801 |
| 802 for attribute in interface.attributes: |
| 803 self._attribute_operation(interface, attribute) |
| 804 self._attribute_operation(interface, attribute, check_dictionaries=False
) |
| 805 |
| 806 for operation in interface.operations: |
| 807 self._attribute_operation(interface, operation) |
| 808 self._attribute_operation(interface, operation, check_dictionaries=False
) |
| 809 |
| 810 # Report all dictionaries and their usage. |
| 811 self._output_examination() |
| 812 # Report all interface marked with NoInterfaceObject and their usage. |
| 813 self._output_examination(check_dictionaries=False) |
| 814 |
| 815 print '\nKey:' |
| 816 print ' (READ-ONLY) - read-only attribute has relationship' |
| 817 print ' (GET/SET) - attribute has relationship' |
| 818 print ' RETURN - operation\'s returned value has relationship' |
| 819 print ' (ARGUMENT) - operation\'s argument(s) has relationship' |
| 820 |
| 821 print '\n\nExamination Complete\n' |
| 822 |
| 823 def _output_examination(self, check_dictionaries=True): |
| 824 # Output diagnostics. First columns is Dictionary or NoInterfaceObject e.g., |
| 825 # | Dictionary | Used In Interface | Usage Operation/Attribute | |
| 826 print '\n\n' |
| 827 title_bar = ['Dictionary', 'Used In Interface', 'Usage Operation/Attribute']
if check_dictionaries \ |
| 828 else ['NoInterfaceObject', 'Used In Interface', 'Usage Operation
/Attribute'] |
| 829 self._tabulate_title(title_bar) |
| 830 diags = self._diag_dictionaries if check_dictionaries else self._diag_no_int
erfaces |
| 831 for diag in diags: |
| 832 self._tabluate([diag['dictionary' if check_dictionaries else 'no_interface
_object'].id, '', '']) |
| 833 for usage in diag['usages']: |
| 834 detail = '' |
| 835 if 'attribute' in usage: |
| 836 attribute_type = 'READ-ONLY' if not usage['argument'] else 'GET/SET' |
| 837 detail = '(%s) %s' % (attribute_type, usage['attribute']) |
| 838 elif 'operation' in usage: |
| 839 detail = '%s %s%s' % ('RETURN' if usage['result'] else '', |
| 840 usage['operation'], |
| 841 '(ARGUMENT)' if usage['argument'] else
'') |
| 842 self._tabluate([None, usage['interface'], detail]) |
| 843 self._tabulate_break() |
| 844 |
| 845 # operation_or_attribute either IDLOperation or IDLAttribute if None then |
| 846 # its a constructor (IDLExtAttrFunctionValue). |
| 847 def _mark_usage(self, interface, operation_or_attribute = None, check_dictiona
ries=True): |
| 848 for diag in self._diag_dictionaries if check_dictionaries else self._diag_no
_interfaces: |
| 849 for usage in diag['usages']: |
| 850 if not usage['interface']: |
| 851 usage['interface'] = interface.id |
| 852 if isinstance(operation_or_attribute, IDLOperation): |
| 853 usage['operation'] = operation_or_attribute.id |
| 854 if check_dictionaries: |
| 855 usage['result'] = hasattr(operation_or_attribute.type, 'dictionary
') and \ |
| 856 operation_or_attribute.type.dictionary == diag['dictionary'].id |
| 857 else: |
| 858 usage['result'] = operation_or_attribute.type.id == diag['no_inter
face_object'].id |
| 859 usage['argument'] = False |
| 860 for argument in operation_or_attribute.arguments: |
| 861 if check_dictionaries: |
| 862 arg = hasattr(argument.type, 'dictionary') and argument.type.dic
tionary == diag['dictionary'].id |
| 863 else: |
| 864 arg = argument.type.id == diag['no_interface_object'].id |
| 865 if arg: |
| 866 usage['argument'] = arg |
| 867 elif isinstance(operation_or_attribute, IDLAttribute): |
| 868 usage['attribute'] = operation_or_attribute.id |
| 869 usage['result'] = True |
| 870 usage['argument'] = not operation_or_attribute.is_read_only |
| 871 elif not operation_or_attribute: |
| 872 # Its a constructor only argument is dictionary or interface with No
InterfaceObject. |
| 873 usage['operation'] = 'constructor' |
| 874 usage['result'] = False |
| 875 usage['argument'] = True |
| 876 |
| 877 def _remember_usage(self, node, check_dictionaries=True): |
| 878 if check_dictionaries: |
| 879 used_types = self._dictionaries_used_types |
| 880 diag_list = self._diag_dictionaries |
| 881 diag_name = 'dictionary' |
| 882 else: |
| 883 used_types = self._no_interfaces_used_types |
| 884 diag_list = self._diag_no_interfaces |
| 885 diag_name = 'no_interface_object' |
| 886 |
| 887 if len(used_types) > 0: |
| 888 normalized_used = list(set(used_types)) |
| 889 for recorded_id in normalized_used: |
| 890 for diag in diag_list: |
| 891 if diag[diag_name].id == recorded_id: |
| 892 diag['usages'].append({'interface': None, 'node': node}) |
| 893 |
| 894 # Iterator function to look for any IDLType that is a dictionary then remember |
| 895 # that dictionary. |
| 896 def _dictionary_used(self, type_node): |
| 897 if hasattr(type_node, 'dictionary'): |
| 898 dictionary_id = type_node.dictionary |
| 899 if self._database.HasDictionary(dictionary_id): |
| 900 for diag_dictionary in self._diag_dictionaries: |
| 901 if diag_dictionary['dictionary'].id == dictionary_id: |
| 902 # Record the dictionary that was referenced. |
| 903 self._dictionaries_used_types.append(dictionary_id) |
| 904 return |
| 905 |
| 906 # If we get to this point, the IDL dictionary was never defined ... oops. |
| 907 print 'DIAGNOSE_ERROR: IDL Dictionary %s doesn\'t exist.' % dictionary_id |
| 908 |
| 909 # Iterator function to look for any IDLType that is an interface marked with |
| 910 # NoInterfaceObject then remember that interface. |
| 911 def _no_interface_used(self, type_node): |
| 912 if hasattr(type_node, 'id'): |
| 913 no_interface_id = type_node.id |
| 914 if self._database.HasInterface(no_interface_id): |
| 915 no_interface = self._database.GetInterface(no_interface_id) |
| 916 if no_interface.is_no_interface_object: |
| 917 for diag_no_interface in self._diag_no_interfaces: |
| 918 if diag_no_interface['no_interface_object'].id == no_interface_id: |
| 919 # Record the interface marked with NoInterfaceObject. |
| 920 self._no_interfaces_used_types.append(no_interface_id) |
| 921 return |
| 922 |
| 923 def _constructors(self, interface, check_dictionaries=True): |
| 924 if check_dictionaries: |
| 925 self._dictionaries_used_types = [] |
| 926 constructor_function = self._dictionary_constructor_types |
| 927 else: |
| 928 self._no_interfaces_used_types = []; |
| 929 constructor_function = self._no_interface_constructor_types |
| 930 |
| 931 map(constructor_function, interface.all(IDLExtAttrFunctionValue)) |
| 932 |
| 933 self._mark_usage(interface, check_dictionaries=check_dictionaries) |
| 934 |
| 935 # Scan an attribute or operation for a dictionary or interface with NoInterfac
eObject |
| 936 # reference. |
| 937 def _attribute_operation(self, interface, operation_attribute, check_dictionar
ies=True): |
| 938 if check_dictionaries: |
| 939 self._dictionaries_used_types = [] |
| 940 used = self._dictionary_used |
| 941 else: |
| 942 self._no_interfaces_used_types = []; |
| 943 used = self._no_interface_used |
| 944 |
| 945 map(used, operation_attribute.all(IDLType)) |
| 946 |
| 947 self._remember_usage(operation_attribute, check_dictionaries=check_dictionar
ies) |
| 948 self._mark_usage(interface, operation_attribute, check_dictionaries=check_di
ctionaries) |
| 949 |
| 950 # Iterator function for map to iterate over all constructor types |
| 951 # (IDLExtAttrFunctionValue) that have a dictionary reference. |
| 952 def _dictionary_constructor_types(self, node): |
| 953 self._dictionaries_used_types = [] |
| 954 map(self._dictionary_used, node.all(IDLType)) |
| 955 self._remember_usage(node) |
| 956 |
| 957 # Iterator function for map to iterate over all constructor types |
| 958 # (IDLExtAttrFunctionValue) that reference an interface with NoInterfaceObject
. |
| 959 def _no_interface_constructor_types(self, node): |
| 960 self._no_interfaces_used_types = []; |
| 961 map(self._no_interface_used, node.all(IDLType)) |
| 962 self._remember_usage(node, check_dictionaries=False) |
| 963 |
| 964 # Maximum width of each column. |
| 965 def _TABULATE_WIDTH(self): |
| 966 return 45 |
| 967 |
| 968 def _tabulate_title(self, row_title): |
| 969 title_separator = "=" * self._TABULATE_WIDTH() |
| 970 self._tabluate([title_separator, title_separator, title_separator]) |
| 971 self._tabluate(row_title) |
| 972 self._tabluate([title_separator, title_separator, title_separator]) |
| 973 |
| 974 def _tabulate_break(self): |
| 975 break_separator = "-" * self._TABULATE_WIDTH() |
| 976 self._tabluate([break_separator, break_separator, break_separator]) |
| 977 |
| 978 def _tabluate(self, columns): |
| 979 """Tabulate a list of columns for a row. Each item in columns is a column |
| 980 value each column will be padded up to _TABULATE_WIDTH. Each |
| 981 column starts/ends with a vertical bar '|' the format a row: |
| 982 |
| 983 | columns[0] | columns[1] | columns[2] | ... | |
| 984 """ |
| 985 if len(columns) > 0: |
| 986 for column in columns: |
| 987 value = '' if not column else column |
| 988 sys.stdout.write('|{0:^{1}}'.format(value, self._TABULATE_WIDTH())) |
| 989 else: |
| 990 sys.stdout.write('|{0:^{1}}'.format('', self._TABULATE_WIDTH())) |
| 991 |
| 992 sys.stdout.write('|\n') |
OLD | NEW |