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, is_dictionary=False) | |
vsm
2015/03/13 14:58:11
Just a nit - I find the name "is_dictionary" a lit
terry
2015/03/13 15:53:31
Yes, good idea. Done.
| |
801 | |
802 for attribute in interface.attributes: | |
803 self._attribute_operation(interface, attribute) | |
804 self._attribute_operation(interface, attribute, is_dictionary=False) | |
805 | |
806 for operation in interface.operations: | |
807 self._attribute_operation(interface, operation) | |
808 self._attribute_operation(interface, operation, is_dictionary=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(is_dictionary=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, is_dictionary=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 is_dictionary \ | |
828 else ['NoInterfaceObject', 'Used In Interface', 'Usage Operation /Attribute'] | |
829 self._tabulate_title(title_bar) | |
830 diags = self._diag_dictionaries if is_dictionary else self._diag_no_interfac es | |
831 for diag in diags: | |
832 self._tabluate([diag['dictionary' if is_dictionary else 'no_interface_obje ct'].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, is_dictionary= True): | |
848 for diag in self._diag_dictionaries if is_dictionary else self._diag_no_inte rfaces: | |
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 is_dictionary: | |
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 is_dictionary: | |
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, is_dictionary=True): | |
878 if is_dictionary: | |
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, is_dictionary=True): | |
924 if is_dictionary: | |
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, is_dictionary=is_dictionary) | |
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, is_dictionary=T rue): | |
938 if is_dictionary: | |
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, is_dictionary=is_dictionary) | |
948 self._mark_usage(interface, operation_attribute, is_dictionary=is_dictionary ) | |
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, is_dictionary=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 |