| @@ 797-961 (lines=165) @@ | ||
| 794 | return s in GetNonHeaderExtensions() |
|
| 795 | ||
| 796 | ||
| 797 | class _IncludeState(object): |
|
| 798 | """Tracks line numbers for includes, and the order in which includes appear. |
|
| 799 | ||
| 800 | include_list contains list of lists of (header, line number) pairs. |
|
| 801 | It's a lists of lists rather than just one flat list to make it |
|
| 802 | easier to update across preprocessor boundaries. |
|
| 803 | ||
| 804 | Call CheckNextIncludeOrder() once for each header in the file, passing |
|
| 805 | in the type constants defined above. Calls in an illegal order will |
|
| 806 | raise an _IncludeError with an appropriate error message. |
|
| 807 | ||
| 808 | """ |
|
| 809 | # self._section will move monotonically through this set. If it ever |
|
| 810 | # needs to move backwards, CheckNextIncludeOrder will raise an error. |
|
| 811 | _INITIAL_SECTION = 0 |
|
| 812 | _MY_H_SECTION = 1 |
|
| 813 | _C_SECTION = 2 |
|
| 814 | _CPP_SECTION = 3 |
|
| 815 | _OTHER_H_SECTION = 4 |
|
| 816 | ||
| 817 | _TYPE_NAMES = { |
|
| 818 | _C_SYS_HEADER: 'C system header', |
|
| 819 | _CPP_SYS_HEADER: 'C++ system header', |
|
| 820 | _LIKELY_MY_HEADER: 'header this file implements', |
|
| 821 | _POSSIBLE_MY_HEADER: 'header this file may implement', |
|
| 822 | _OTHER_HEADER: 'other header', |
|
| 823 | } |
|
| 824 | _SECTION_NAMES = { |
|
| 825 | _INITIAL_SECTION: "... nothing. (This can't be an error.)", |
|
| 826 | _MY_H_SECTION: 'a header this file implements', |
|
| 827 | _C_SECTION: 'C system header', |
|
| 828 | _CPP_SECTION: 'C++ system header', |
|
| 829 | _OTHER_H_SECTION: 'other header', |
|
| 830 | } |
|
| 831 | ||
| 832 | def __init__(self): |
|
| 833 | self.include_list = [[]] |
|
| 834 | self._section = None |
|
| 835 | self._last_header = None |
|
| 836 | self.ResetSection('') |
|
| 837 | ||
| 838 | def FindHeader(self, header): |
|
| 839 | """Check if a header has already been included. |
|
| 840 | ||
| 841 | Args: |
|
| 842 | header: header to check. |
|
| 843 | Returns: |
|
| 844 | Line number of previous occurrence, or -1 if the header has not |
|
| 845 | been seen before. |
|
| 846 | """ |
|
| 847 | for section_list in self.include_list: |
|
| 848 | for f in section_list: |
|
| 849 | if f[0] == header: |
|
| 850 | return f[1] |
|
| 851 | return -1 |
|
| 852 | ||
| 853 | def ResetSection(self, directive): |
|
| 854 | """Reset section checking for preprocessor directive. |
|
| 855 | ||
| 856 | Args: |
|
| 857 | directive: preprocessor directive (e.g. "if", "else"). |
|
| 858 | """ |
|
| 859 | # The name of the current section. |
|
| 860 | self._section = self._INITIAL_SECTION |
|
| 861 | # The path of last found header. |
|
| 862 | self._last_header = '' |
|
| 863 | ||
| 864 | # Update list of includes. Note that we never pop from the |
|
| 865 | # include list. |
|
| 866 | if directive in ('if', 'ifdef', 'ifndef'): |
|
| 867 | self.include_list.append([]) |
|
| 868 | elif directive in ('else', 'elif'): |
|
| 869 | self.include_list[-1] = [] |
|
| 870 | ||
| 871 | def SetLastHeader(self, header_path): |
|
| 872 | self._last_header = header_path |
|
| 873 | ||
| 874 | def CanonicalizeAlphabeticalOrder(self, header_path): |
|
| 875 | """Returns a path canonicalized for alphabetical comparison. |
|
| 876 | ||
| 877 | - replaces "-" with "_" so they both cmp the same. |
|
| 878 | - removes '-inl' since we don't require them to be after the main header. |
|
| 879 | - lowercase everything, just in case. |
|
| 880 | ||
| 881 | Args: |
|
| 882 | header_path: Path to be canonicalized. |
|
| 883 | ||
| 884 | Returns: |
|
| 885 | Canonicalized path. |
|
| 886 | """ |
|
| 887 | return header_path.replace('-inl.h', '.h').replace('-', '_').lower() |
|
| 888 | ||
| 889 | def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path): |
|
| 890 | """Check if a header is in alphabetical order with the previous header. |
|
| 891 | ||
| 892 | Args: |
|
| 893 | clean_lines: A CleansedLines instance containing the file. |
|
| 894 | linenum: The number of the line to check. |
|
| 895 | header_path: Canonicalized header to be checked. |
|
| 896 | ||
| 897 | Returns: |
|
| 898 | Returns true if the header is in alphabetical order. |
|
| 899 | """ |
|
| 900 | # If previous section is different from current section, _last_header will |
|
| 901 | # be reset to empty string, so it's always less than current header. |
|
| 902 | # |
|
| 903 | # If previous line was a blank line, assume that the headers are |
|
| 904 | # intentionally sorted the way they are. |
|
| 905 | if (self._last_header > header_path and |
|
| 906 | Match(r'^\s*#\s*include\b', clean_lines.elided[linenum - 1])): |
|
| 907 | return False |
|
| 908 | return True |
|
| 909 | ||
| 910 | def CheckNextIncludeOrder(self, header_type): |
|
| 911 | """Returns a non-empty error message if the next header is out of order. |
|
| 912 | ||
| 913 | This function also updates the internal state to be ready to check |
|
| 914 | the next include. |
|
| 915 | ||
| 916 | Args: |
|
| 917 | header_type: One of the _XXX_HEADER constants defined above. |
|
| 918 | ||
| 919 | Returns: |
|
| 920 | The empty string if the header is in the right order, or an |
|
| 921 | error message describing what's wrong. |
|
| 922 | ||
| 923 | """ |
|
| 924 | error_message = ('Found %s after %s' % |
|
| 925 | (self._TYPE_NAMES[header_type], |
|
| 926 | self._SECTION_NAMES[self._section])) |
|
| 927 | ||
| 928 | last_section = self._section |
|
| 929 | ||
| 930 | if header_type == _C_SYS_HEADER: |
|
| 931 | if self._section <= self._C_SECTION: |
|
| 932 | self._section = self._C_SECTION |
|
| 933 | else: |
|
| 934 | self._last_header = '' |
|
| 935 | return error_message |
|
| 936 | elif header_type == _CPP_SYS_HEADER: |
|
| 937 | if self._section <= self._CPP_SECTION: |
|
| 938 | self._section = self._CPP_SECTION |
|
| 939 | else: |
|
| 940 | self._last_header = '' |
|
| 941 | return error_message |
|
| 942 | elif header_type == _LIKELY_MY_HEADER: |
|
| 943 | if self._section <= self._MY_H_SECTION: |
|
| 944 | self._section = self._MY_H_SECTION |
|
| 945 | else: |
|
| 946 | self._section = self._OTHER_H_SECTION |
|
| 947 | elif header_type == _POSSIBLE_MY_HEADER: |
|
| 948 | if self._section <= self._MY_H_SECTION: |
|
| 949 | self._section = self._MY_H_SECTION |
|
| 950 | else: |
|
| 951 | # This will always be the fallback because we're not sure |
|
| 952 | # enough that the header is associated with this file. |
|
| 953 | self._section = self._OTHER_H_SECTION |
|
| 954 | else: |
|
| 955 | assert header_type == _OTHER_HEADER |
|
| 956 | self._section = self._OTHER_H_SECTION |
|
| 957 | ||
| 958 | if last_section != self._section: |
|
| 959 | self._last_header = '' |
|
| 960 | ||
| 961 | return '' |
|
| 962 | ||
| 963 | ||
| 964 | class _CppLintState(object): |
|
| @@ 797-961 (lines=165) @@ | ||
| 794 | return s in GetNonHeaderExtensions() |
|
| 795 | ||
| 796 | ||
| 797 | class _IncludeState(object): |
|
| 798 | """Tracks line numbers for includes, and the order in which includes appear. |
|
| 799 | ||
| 800 | include_list contains list of lists of (header, line number) pairs. |
|
| 801 | It's a lists of lists rather than just one flat list to make it |
|
| 802 | easier to update across preprocessor boundaries. |
|
| 803 | ||
| 804 | Call CheckNextIncludeOrder() once for each header in the file, passing |
|
| 805 | in the type constants defined above. Calls in an illegal order will |
|
| 806 | raise an _IncludeError with an appropriate error message. |
|
| 807 | ||
| 808 | """ |
|
| 809 | # self._section will move monotonically through this set. If it ever |
|
| 810 | # needs to move backwards, CheckNextIncludeOrder will raise an error. |
|
| 811 | _INITIAL_SECTION = 0 |
|
| 812 | _MY_H_SECTION = 1 |
|
| 813 | _C_SECTION = 2 |
|
| 814 | _CPP_SECTION = 3 |
|
| 815 | _OTHER_H_SECTION = 4 |
|
| 816 | ||
| 817 | _TYPE_NAMES = { |
|
| 818 | _C_SYS_HEADER: 'C system header', |
|
| 819 | _CPP_SYS_HEADER: 'C++ system header', |
|
| 820 | _LIKELY_MY_HEADER: 'header this file implements', |
|
| 821 | _POSSIBLE_MY_HEADER: 'header this file may implement', |
|
| 822 | _OTHER_HEADER: 'other header', |
|
| 823 | } |
|
| 824 | _SECTION_NAMES = { |
|
| 825 | _INITIAL_SECTION: "... nothing. (This can't be an error.)", |
|
| 826 | _MY_H_SECTION: 'a header this file implements', |
|
| 827 | _C_SECTION: 'C system header', |
|
| 828 | _CPP_SECTION: 'C++ system header', |
|
| 829 | _OTHER_H_SECTION: 'other header', |
|
| 830 | } |
|
| 831 | ||
| 832 | def __init__(self): |
|
| 833 | self.include_list = [[]] |
|
| 834 | self._section = None |
|
| 835 | self._last_header = None |
|
| 836 | self.ResetSection('') |
|
| 837 | ||
| 838 | def FindHeader(self, header): |
|
| 839 | """Check if a header has already been included. |
|
| 840 | ||
| 841 | Args: |
|
| 842 | header: header to check. |
|
| 843 | Returns: |
|
| 844 | Line number of previous occurrence, or -1 if the header has not |
|
| 845 | been seen before. |
|
| 846 | """ |
|
| 847 | for section_list in self.include_list: |
|
| 848 | for f in section_list: |
|
| 849 | if f[0] == header: |
|
| 850 | return f[1] |
|
| 851 | return -1 |
|
| 852 | ||
| 853 | def ResetSection(self, directive): |
|
| 854 | """Reset section checking for preprocessor directive. |
|
| 855 | ||
| 856 | Args: |
|
| 857 | directive: preprocessor directive (e.g. "if", "else"). |
|
| 858 | """ |
|
| 859 | # The name of the current section. |
|
| 860 | self._section = self._INITIAL_SECTION |
|
| 861 | # The path of last found header. |
|
| 862 | self._last_header = '' |
|
| 863 | ||
| 864 | # Update list of includes. Note that we never pop from the |
|
| 865 | # include list. |
|
| 866 | if directive in ('if', 'ifdef', 'ifndef'): |
|
| 867 | self.include_list.append([]) |
|
| 868 | elif directive in ('else', 'elif'): |
|
| 869 | self.include_list[-1] = [] |
|
| 870 | ||
| 871 | def SetLastHeader(self, header_path): |
|
| 872 | self._last_header = header_path |
|
| 873 | ||
| 874 | def CanonicalizeAlphabeticalOrder(self, header_path): |
|
| 875 | """Returns a path canonicalized for alphabetical comparison. |
|
| 876 | ||
| 877 | - replaces "-" with "_" so they both cmp the same. |
|
| 878 | - removes '-inl' since we don't require them to be after the main header. |
|
| 879 | - lowercase everything, just in case. |
|
| 880 | ||
| 881 | Args: |
|
| 882 | header_path: Path to be canonicalized. |
|
| 883 | ||
| 884 | Returns: |
|
| 885 | Canonicalized path. |
|
| 886 | """ |
|
| 887 | return header_path.replace('-inl.h', '.h').replace('-', '_').lower() |
|
| 888 | ||
| 889 | def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path): |
|
| 890 | """Check if a header is in alphabetical order with the previous header. |
|
| 891 | ||
| 892 | Args: |
|
| 893 | clean_lines: A CleansedLines instance containing the file. |
|
| 894 | linenum: The number of the line to check. |
|
| 895 | header_path: Canonicalized header to be checked. |
|
| 896 | ||
| 897 | Returns: |
|
| 898 | Returns true if the header is in alphabetical order. |
|
| 899 | """ |
|
| 900 | # If previous section is different from current section, _last_header will |
|
| 901 | # be reset to empty string, so it's always less than current header. |
|
| 902 | # |
|
| 903 | # If previous line was a blank line, assume that the headers are |
|
| 904 | # intentionally sorted the way they are. |
|
| 905 | if (self._last_header > header_path and |
|
| 906 | Match(r'^\s*#\s*include\b', clean_lines.elided[linenum - 1])): |
|
| 907 | return False |
|
| 908 | return True |
|
| 909 | ||
| 910 | def CheckNextIncludeOrder(self, header_type): |
|
| 911 | """Returns a non-empty error message if the next header is out of order. |
|
| 912 | ||
| 913 | This function also updates the internal state to be ready to check |
|
| 914 | the next include. |
|
| 915 | ||
| 916 | Args: |
|
| 917 | header_type: One of the _XXX_HEADER constants defined above. |
|
| 918 | ||
| 919 | Returns: |
|
| 920 | The empty string if the header is in the right order, or an |
|
| 921 | error message describing what's wrong. |
|
| 922 | ||
| 923 | """ |
|
| 924 | error_message = ('Found %s after %s' % |
|
| 925 | (self._TYPE_NAMES[header_type], |
|
| 926 | self._SECTION_NAMES[self._section])) |
|
| 927 | ||
| 928 | last_section = self._section |
|
| 929 | ||
| 930 | if header_type == _C_SYS_HEADER: |
|
| 931 | if self._section <= self._C_SECTION: |
|
| 932 | self._section = self._C_SECTION |
|
| 933 | else: |
|
| 934 | self._last_header = '' |
|
| 935 | return error_message |
|
| 936 | elif header_type == _CPP_SYS_HEADER: |
|
| 937 | if self._section <= self._CPP_SECTION: |
|
| 938 | self._section = self._CPP_SECTION |
|
| 939 | else: |
|
| 940 | self._last_header = '' |
|
| 941 | return error_message |
|
| 942 | elif header_type == _LIKELY_MY_HEADER: |
|
| 943 | if self._section <= self._MY_H_SECTION: |
|
| 944 | self._section = self._MY_H_SECTION |
|
| 945 | else: |
|
| 946 | self._section = self._OTHER_H_SECTION |
|
| 947 | elif header_type == _POSSIBLE_MY_HEADER: |
|
| 948 | if self._section <= self._MY_H_SECTION: |
|
| 949 | self._section = self._MY_H_SECTION |
|
| 950 | else: |
|
| 951 | # This will always be the fallback because we're not sure |
|
| 952 | # enough that the header is associated with this file. |
|
| 953 | self._section = self._OTHER_H_SECTION |
|
| 954 | else: |
|
| 955 | assert header_type == _OTHER_HEADER |
|
| 956 | self._section = self._OTHER_H_SECTION |
|
| 957 | ||
| 958 | if last_section != self._section: |
|
| 959 | self._last_header = '' |
|
| 960 | ||
| 961 | return '' |
|
| 962 | ||
| 963 | ||
| 964 | class _CppLintState(object): |
|