]>
Commit | Line | Data |
---|---|---|
53e6db90 DC |
1 | # Copyright 2015 Google Inc. All Rights Reserved. |
2 | # | |
3 | # Licensed under the Apache License, Version 2.0 (the "License"); | |
4 | # you may not use this file except in compliance with the License. | |
5 | # You may obtain a copy of the License at | |
6 | # | |
7 | # http://www.apache.org/licenses/LICENSE-2.0 | |
8 | # | |
9 | # Unless required by applicable law or agreed to in writing, software | |
10 | # distributed under the License is distributed on an "AS IS" BASIS, | |
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 | # See the License for the specific language governing permissions and | |
13 | # limitations under the License. | |
14 | """Join logical lines together. | |
15 | ||
16 | Determine how many lines can be joined into one line. For instance, we could | |
17 | join these statements into one line: | |
18 | ||
19 | if a == 42: | |
20 | continue | |
21 | ||
22 | like this: | |
23 | ||
24 | if a == 42: continue | |
25 | ||
26 | There are a few restrictions: | |
27 | ||
28 | 1. The lines should have been joined in the original source. | |
29 | 2. The joined lines must not go over the column boundary if placed on the same | |
30 | line. | |
31 | 3. They need to be very simple statements. | |
32 | ||
33 | Note: Because we don't allow the use of a semicolon to separate statements, it | |
34 | follows that there can only be at most two lines to join. | |
35 | """ | |
36 | ||
37 | from yapf.yapflib import style | |
38 | ||
39 | _CLASS_OR_FUNC = frozenset({'def', 'class'}) | |
40 | ||
41 | ||
42 | def CanMergeMultipleLines(lines, last_was_merged=False): | |
43 | """Determine if multiple lines can be joined into one. | |
44 | ||
45 | Arguments: | |
46 | lines: (list of LogicalLine) This is a splice of LogicalLines from the full | |
47 | code base. | |
48 | last_was_merged: (bool) The last line was merged. | |
49 | ||
50 | Returns: | |
51 | True if two consecutive lines can be joined together. In reality, this will | |
52 | only happen if two consecutive lines can be joined, due to the style guide. | |
53 | """ | |
54 | # The indentation amount for the starting line (number of spaces). | |
55 | indent_amt = lines[0].depth * style.Get('INDENT_WIDTH') | |
56 | if len(lines) == 1 or indent_amt > style.Get('COLUMN_LIMIT'): | |
57 | return False | |
58 | ||
59 | if (len(lines) >= 3 and lines[2].depth >= lines[1].depth and | |
60 | lines[0].depth != lines[2].depth): | |
61 | # If lines[2]'s depth is greater than or equal to line[1]'s depth, we're not | |
62 | # looking at a single statement (e.g., if-then, while, etc.). A following | |
63 | # line with the same depth as the first line isn't part of the lines we | |
64 | # would want to combine. | |
65 | return False # Don't merge more than two lines together. | |
66 | ||
67 | if lines[0].first.value in _CLASS_OR_FUNC: | |
68 | # Don't join lines onto the starting line of a class or function. | |
69 | return False | |
70 | ||
71 | limit = style.Get('COLUMN_LIMIT') - indent_amt | |
72 | if lines[0].last.total_length < limit: | |
73 | limit -= lines[0].last.total_length | |
74 | ||
75 | if lines[0].first.value == 'if': | |
76 | return _CanMergeLineIntoIfStatement(lines, limit) | |
77 | if last_was_merged and lines[0].first.value in {'elif', 'else'}: | |
78 | return _CanMergeLineIntoIfStatement(lines, limit) | |
79 | ||
80 | # TODO(morbo): Other control statements? | |
81 | ||
82 | return False | |
83 | ||
84 | ||
85 | def _CanMergeLineIntoIfStatement(lines, limit): | |
86 | """Determine if we can merge a short if-then statement into one line. | |
87 | ||
88 | Two lines of an if-then statement can be merged if they were that way in the | |
89 | original source, fit on the line without going over the column limit, and are | |
90 | considered "simple" statements --- typically statements like 'pass', | |
91 | 'continue', and 'break'. | |
92 | ||
93 | Arguments: | |
94 | lines: (list of LogicalLine) The lines we are wanting to merge. | |
95 | limit: (int) The amount of space remaining on the line. | |
96 | ||
97 | Returns: | |
98 | True if the lines can be merged, False otherwise. | |
99 | """ | |
100 | if len(lines[1].tokens) == 1 and lines[1].last.is_multiline_string: | |
101 | # This might be part of a multiline shebang. | |
102 | return True | |
103 | if lines[0].lineno != lines[1].lineno: | |
104 | # Don't merge lines if the original lines weren't merged. | |
105 | return False | |
106 | if lines[1].last.total_length >= limit: | |
107 | # Don't merge lines if the result goes over the column limit. | |
108 | return False | |
109 | return style.Get('JOIN_MULTIPLE_LINES') |