reformatter.py 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788
  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. """Decide what the format for the code should be.
  15. The `logical_line.LogicalLine`s are now ready to be formatted. LogicalLInes that
  16. can be merged together are. The best formatting is returned as a string.
  17. Reformat(): the main function exported by this module.
  18. """
  19. import collections
  20. import heapq
  21. import re
  22. from yapf_third_party._ylib2to3 import pytree
  23. from yapf_third_party._ylib2to3.pgen2 import token
  24. from yapf.pytree import pytree_utils
  25. from yapf.yapflib import format_decision_state
  26. from yapf.yapflib import format_token
  27. from yapf.yapflib import line_joiner
  28. from yapf.yapflib import style
  29. from yapf.yapflib import verifier
  30. def Reformat(llines, verify=False, lines=None):
  31. """Reformat the logical lines.
  32. Arguments:
  33. llines: (list of logical_line.LogicalLine) Lines we want to format.
  34. verify: (bool) True if reformatted code should be verified for syntax.
  35. lines: (set of int) The lines which can be modified or None if there is no
  36. line range restriction.
  37. Returns:
  38. A string representing the reformatted code.
  39. """
  40. final_lines = []
  41. prev_line = None # The previous line.
  42. indent_width = style.Get('INDENT_WIDTH')
  43. for lline in _SingleOrMergedLines(llines):
  44. first_token = lline.first
  45. _FormatFirstToken(first_token, lline.depth, prev_line, final_lines)
  46. indent_amt = indent_width * lline.depth
  47. state = format_decision_state.FormatDecisionState(lline, indent_amt)
  48. state.MoveStateToNextToken()
  49. if not lline.disable:
  50. if lline.first.is_comment:
  51. lline.first.value = lline.first.value.rstrip()
  52. elif lline.last.is_comment:
  53. lline.last.value = lline.last.value.rstrip()
  54. if prev_line and prev_line.disable:
  55. # Keep the vertical spacing between a disabled and enabled formatting
  56. # region.
  57. _RetainRequiredVerticalSpacingBetweenTokens(lline.first, prev_line.last,
  58. lines)
  59. if any(tok.is_comment for tok in lline.tokens):
  60. _RetainVerticalSpacingBeforeComments(lline)
  61. if lline.disable or _LineHasContinuationMarkers(lline):
  62. _RetainHorizontalSpacing(lline)
  63. _RetainRequiredVerticalSpacing(lline, prev_line, lines)
  64. _EmitLineUnformatted(state)
  65. elif (_LineContainsPylintDisableLineTooLong(lline) or
  66. _LineContainsI18n(lline)):
  67. # Don't modify vertical spacing, but fix any horizontal spacing issues.
  68. _RetainRequiredVerticalSpacing(lline, prev_line, lines)
  69. _EmitLineUnformatted(state)
  70. elif _CanPlaceOnSingleLine(lline) and not any(tok.must_break_before
  71. for tok in lline.tokens):
  72. # The logical line fits on one line.
  73. while state.next_token:
  74. state.AddTokenToState(newline=False, dry_run=False)
  75. elif not _AnalyzeSolutionSpace(state):
  76. # Failsafe mode. If there isn't a solution to the line, then just emit
  77. # it as is.
  78. state = format_decision_state.FormatDecisionState(lline, indent_amt)
  79. state.MoveStateToNextToken()
  80. _RetainHorizontalSpacing(lline)
  81. _RetainRequiredVerticalSpacing(lline, prev_line, None)
  82. _EmitLineUnformatted(state)
  83. final_lines.append(lline)
  84. prev_line = lline
  85. _AlignTrailingComments(final_lines)
  86. return _FormatFinalLines(final_lines, verify)
  87. def _RetainHorizontalSpacing(line):
  88. """Retain all horizontal spacing between tokens."""
  89. for tok in line.tokens:
  90. tok.RetainHorizontalSpacing(line.first.column, line.depth)
  91. def _RetainRequiredVerticalSpacing(cur_line, prev_line, lines):
  92. """Retain all vertical spacing between lines."""
  93. prev_tok = None
  94. if prev_line is not None:
  95. prev_tok = prev_line.last
  96. if cur_line.disable:
  97. # After the first token we are acting on a single line. So if it is
  98. # disabled we must not reformat.
  99. lines = set()
  100. for cur_tok in cur_line.tokens:
  101. _RetainRequiredVerticalSpacingBetweenTokens(cur_tok, prev_tok, lines)
  102. prev_tok = cur_tok
  103. def _RetainRequiredVerticalSpacingBetweenTokens(cur_tok, prev_tok, lines):
  104. """Retain vertical spacing between two tokens if not in editable range."""
  105. if prev_tok is None:
  106. return
  107. if prev_tok.is_string:
  108. prev_lineno = prev_tok.lineno + prev_tok.value.count('\n')
  109. elif prev_tok.is_pseudo:
  110. if not prev_tok.previous_token.is_multiline_string:
  111. prev_lineno = prev_tok.previous_token.lineno
  112. else:
  113. prev_lineno = prev_tok.lineno
  114. else:
  115. prev_lineno = prev_tok.lineno
  116. if cur_tok.is_comment:
  117. cur_lineno = cur_tok.lineno - cur_tok.value.count('\n')
  118. else:
  119. cur_lineno = cur_tok.lineno
  120. if not prev_tok.is_comment and prev_tok.value.endswith('\\'):
  121. prev_lineno += prev_tok.value.count('\n')
  122. required_newlines = cur_lineno - prev_lineno
  123. if cur_tok.is_comment and not prev_tok.is_comment:
  124. # Don't adjust between a comment and non-comment.
  125. pass
  126. elif lines and lines.intersection(range(prev_lineno, cur_lineno + 1)):
  127. desired_newlines = cur_tok.whitespace_prefix.count('\n')
  128. whitespace_lines = range(prev_lineno + 1, cur_lineno)
  129. deletable_lines = len(lines.intersection(whitespace_lines))
  130. required_newlines = max(required_newlines - deletable_lines,
  131. desired_newlines)
  132. cur_tok.AdjustNewlinesBefore(required_newlines)
  133. def _RetainVerticalSpacingBeforeComments(line):
  134. """Retain vertical spacing before comments."""
  135. prev_token = None
  136. for tok in line.tokens:
  137. if tok.is_comment and prev_token:
  138. if tok.lineno - tok.value.count('\n') - prev_token.lineno > 1:
  139. tok.AdjustNewlinesBefore(ONE_BLANK_LINE)
  140. prev_token = tok
  141. def _EmitLineUnformatted(state):
  142. """Emit the line without formatting.
  143. The line contains code that if reformatted would break a non-syntactic
  144. convention. E.g., i18n comments and function calls are tightly bound by
  145. convention. Instead, we calculate when / if a newline should occur and honor
  146. that. But otherwise the code emitted will be the same as the original code.
  147. Arguments:
  148. state: (format_decision_state.FormatDecisionState) The format decision
  149. state.
  150. """
  151. while state.next_token:
  152. previous_token = state.next_token.previous_token
  153. previous_lineno = previous_token.lineno
  154. if previous_token.is_multiline_string or previous_token.is_string:
  155. previous_lineno += previous_token.value.count('\n')
  156. if previous_token.is_continuation:
  157. newline = False
  158. else:
  159. newline = state.next_token.lineno > previous_lineno
  160. state.AddTokenToState(newline=newline, dry_run=False)
  161. def _LineContainsI18n(line):
  162. """Return true if there are i18n comments or function calls in the line.
  163. I18n comments and pseudo-function calls are closely related. They cannot
  164. be moved apart without breaking i18n.
  165. Arguments:
  166. line: (logical_line.LogicalLine) The line currently being formatted.
  167. Returns:
  168. True if the line contains i18n comments or function calls. False otherwise.
  169. """
  170. if style.Get('I18N_COMMENT'):
  171. for tok in line.tokens:
  172. if tok.is_comment and re.match(style.Get('I18N_COMMENT'), tok.value):
  173. # Contains an i18n comment.
  174. return True
  175. if style.Get('I18N_FUNCTION_CALL'):
  176. length = len(line.tokens)
  177. for index in range(length - 1):
  178. if (line.tokens[index + 1].value == '(' and
  179. line.tokens[index].value in style.Get('I18N_FUNCTION_CALL')):
  180. return True
  181. return False
  182. def _LineContainsPylintDisableLineTooLong(line):
  183. """Return true if there is a "pylint: disable=line-too-long" comment."""
  184. return re.search(r'\bpylint:\s+disable=line-too-long\b', line.last.value)
  185. def _LineHasContinuationMarkers(line):
  186. """Return true if the line has continuation markers in it."""
  187. return any(tok.is_continuation for tok in line.tokens)
  188. def _CanPlaceOnSingleLine(line):
  189. """Determine if the logical line can go on a single line.
  190. Arguments:
  191. line: (logical_line.LogicalLine) The line currently being formatted.
  192. Returns:
  193. True if the line can or should be added to a single line. False otherwise.
  194. """
  195. token_names = [x.name for x in line.tokens]
  196. if (style.Get('FORCE_MULTILINE_DICT') and 'LBRACE' in token_names):
  197. return False
  198. indent_amt = style.Get('INDENT_WIDTH') * line.depth
  199. last = line.last
  200. last_index = -1
  201. if (last.is_pylint_comment or last.is_pytype_comment or
  202. last.is_copybara_comment):
  203. last = last.previous_token
  204. last_index = -2
  205. if last is None:
  206. return True
  207. return (last.total_length + indent_amt <= style.Get('COLUMN_LIMIT') and
  208. not any(tok.is_comment for tok in line.tokens[:last_index]))
  209. def _AlignTrailingComments(final_lines):
  210. """Align trailing comments to the same column."""
  211. final_lines_index = 0
  212. while final_lines_index < len(final_lines):
  213. line = final_lines[final_lines_index]
  214. assert line.tokens
  215. processed_content = False
  216. for tok in line.tokens:
  217. if (tok.is_comment and isinstance(tok.spaces_required_before, list) and
  218. tok.value.startswith('#')):
  219. # All trailing comments and comments that appear on a line by themselves
  220. # in this block should be indented at the same level. The block is
  221. # terminated by an empty line or EOF. Enumerate through each line in
  222. # the block and calculate the max line length. Once complete, use the
  223. # first col value greater than that value and create the necessary for
  224. # each line accordingly.
  225. all_pc_line_lengths = [] # All pre-comment line lengths
  226. max_line_length = 0
  227. while True:
  228. # EOF
  229. if final_lines_index + len(all_pc_line_lengths) == len(final_lines):
  230. break
  231. this_line = final_lines[final_lines_index + len(all_pc_line_lengths)]
  232. # Blank line - note that content is preformatted so we don't need to
  233. # worry about spaces/tabs; a blank line will always be '\n\n'.
  234. assert this_line.tokens
  235. if (all_pc_line_lengths and
  236. this_line.tokens[0].formatted_whitespace_prefix.startswith('\n\n')
  237. ):
  238. break
  239. if this_line.disable:
  240. all_pc_line_lengths.append([])
  241. continue
  242. # Calculate the length of each line in this logical line.
  243. line_content = ''
  244. pc_line_lengths = []
  245. for line_tok in this_line.tokens:
  246. whitespace_prefix = line_tok.formatted_whitespace_prefix
  247. newline_index = whitespace_prefix.rfind('\n')
  248. if newline_index != -1:
  249. max_line_length = max(max_line_length, len(line_content))
  250. line_content = ''
  251. whitespace_prefix = whitespace_prefix[newline_index + 1:]
  252. if line_tok.is_comment:
  253. pc_line_lengths.append(len(line_content))
  254. else:
  255. line_content += '{}{}'.format(whitespace_prefix, line_tok.value)
  256. if pc_line_lengths:
  257. max_line_length = max(max_line_length, max(pc_line_lengths))
  258. all_pc_line_lengths.append(pc_line_lengths)
  259. # Calculate the aligned column value
  260. max_line_length += 2
  261. aligned_col = None
  262. for potential_col in tok.spaces_required_before:
  263. if potential_col > max_line_length:
  264. aligned_col = potential_col
  265. break
  266. if aligned_col is None:
  267. aligned_col = max_line_length
  268. # Update the comment token values based on the aligned values
  269. for all_pc_line_lengths_index, pc_line_lengths in enumerate(
  270. all_pc_line_lengths):
  271. if not pc_line_lengths:
  272. continue
  273. this_line = final_lines[final_lines_index + all_pc_line_lengths_index]
  274. pc_line_length_index = 0
  275. for line_tok in this_line.tokens:
  276. if line_tok.is_comment:
  277. assert pc_line_length_index < len(pc_line_lengths)
  278. assert pc_line_lengths[pc_line_length_index] < aligned_col
  279. # Note that there may be newlines embedded in the comments, so
  280. # we need to apply a whitespace prefix to each line.
  281. whitespace = ' ' * (
  282. aligned_col - pc_line_lengths[pc_line_length_index] - 1)
  283. pc_line_length_index += 1
  284. line_content = []
  285. for comment_line_index, comment_line in enumerate(
  286. line_tok.value.split('\n')):
  287. line_content.append('{}{}'.format(whitespace,
  288. comment_line.strip()))
  289. if comment_line_index == 0:
  290. whitespace = ' ' * (aligned_col - 1)
  291. line_content = '\n'.join(line_content)
  292. # Account for initial whitespace already slated for the
  293. # beginning of the line.
  294. existing_whitespace_prefix = \
  295. line_tok.formatted_whitespace_prefix.lstrip('\n')
  296. if line_content.startswith(existing_whitespace_prefix):
  297. line_content = line_content[len(existing_whitespace_prefix):]
  298. line_tok.value = line_content
  299. assert pc_line_length_index == len(pc_line_lengths)
  300. final_lines_index += len(all_pc_line_lengths)
  301. processed_content = True
  302. break
  303. if not processed_content:
  304. final_lines_index += 1
  305. def _FormatFinalLines(final_lines, verify):
  306. """Compose the final output from the finalized lines."""
  307. formatted_code = []
  308. for line in final_lines:
  309. formatted_line = []
  310. for tok in line.tokens:
  311. if not tok.is_pseudo:
  312. formatted_line.append(tok.formatted_whitespace_prefix)
  313. formatted_line.append(tok.value)
  314. elif (not tok.next_token.whitespace_prefix.startswith('\n') and
  315. not tok.next_token.whitespace_prefix.startswith(' ')):
  316. if (tok.previous_token.value == ':' or
  317. tok.next_token.value not in ',}])'):
  318. formatted_line.append(' ')
  319. formatted_code.append(''.join(formatted_line))
  320. if verify:
  321. verifier.VerifyCode(formatted_code[-1])
  322. return ''.join(formatted_code) + '\n'
  323. class _StateNode(object):
  324. """An edge in the solution space from 'previous.state' to 'state'.
  325. Attributes:
  326. state: (format_decision_state.FormatDecisionState) The format decision state
  327. for this node.
  328. newline: If True, then on the edge from 'previous.state' to 'state' a
  329. newline is inserted.
  330. previous: (_StateNode) The previous state node in the graph.
  331. """
  332. # TODO(morbo): Add a '__cmp__' method.
  333. def __init__(self, state, newline, previous):
  334. self.state = state.Clone()
  335. self.newline = newline
  336. self.previous = previous
  337. def __repr__(self): # pragma: no cover
  338. return 'StateNode(state=[\n{0}\n], newline={1})'.format(
  339. self.state, self.newline)
  340. # A tuple of (penalty, count) that is used to prioritize the BFS. In case of
  341. # equal penalties, we prefer states that were inserted first. During state
  342. # generation, we make sure that we insert states first that break the line as
  343. # late as possible.
  344. _OrderedPenalty = collections.namedtuple('OrderedPenalty', ['penalty', 'count'])
  345. # An item in the prioritized BFS search queue. The 'StateNode's 'state' has
  346. # the given '_OrderedPenalty'.
  347. _QueueItem = collections.namedtuple('QueueItem',
  348. ['ordered_penalty', 'state_node'])
  349. def _AnalyzeSolutionSpace(initial_state):
  350. """Analyze the entire solution space starting from initial_state.
  351. This implements a variant of Dijkstra's algorithm on the graph that spans
  352. the solution space (LineStates are the nodes). The algorithm tries to find
  353. the shortest path (the one with the lowest penalty) from 'initial_state' to
  354. the state where all tokens are placed.
  355. Arguments:
  356. initial_state: (format_decision_state.FormatDecisionState) The initial state
  357. to start the search from.
  358. Returns:
  359. True if a formatting solution was found. False otherwise.
  360. """
  361. count = 0
  362. seen = set()
  363. p_queue = []
  364. # Insert start element.
  365. node = _StateNode(initial_state, False, None)
  366. heapq.heappush(p_queue, _QueueItem(_OrderedPenalty(0, count), node))
  367. count += 1
  368. while p_queue:
  369. item = p_queue[0]
  370. penalty = item.ordered_penalty.penalty
  371. node = item.state_node
  372. if not node.state.next_token:
  373. break
  374. heapq.heappop(p_queue)
  375. if count > 10000:
  376. node.state.ignore_stack_for_comparison = True
  377. # Unconditionally add the state and check if it was present to avoid having
  378. # to hash it twice in the common case (state hashing is expensive).
  379. before_seen_count = len(seen)
  380. seen.add(node.state)
  381. # If seen didn't change size, the state was already present.
  382. if before_seen_count == len(seen):
  383. continue
  384. # FIXME(morbo): Add a 'decision' element?
  385. count = _AddNextStateToQueue(penalty, node, False, count, p_queue)
  386. count = _AddNextStateToQueue(penalty, node, True, count, p_queue)
  387. if not p_queue:
  388. # We weren't able to find a solution. Do nothing.
  389. return False
  390. _ReconstructPath(initial_state, heapq.heappop(p_queue).state_node)
  391. return True
  392. def _AddNextStateToQueue(penalty, previous_node, newline, count, p_queue):
  393. """Add the following state to the analysis queue.
  394. Assume the current state is 'previous_node' and has been reached with a
  395. penalty of 'penalty'. Insert a line break if 'newline' is True.
  396. Arguments:
  397. penalty: (int) The penalty associated with the path up to this point.
  398. previous_node: (_StateNode) The last _StateNode inserted into the priority
  399. queue.
  400. newline: (bool) Add a newline if True.
  401. count: (int) The number of elements in the queue.
  402. p_queue: (heapq) The priority queue representing the solution space.
  403. Returns:
  404. The updated number of elements in the queue.
  405. """
  406. must_split = previous_node.state.MustSplit()
  407. if newline and not previous_node.state.CanSplit(must_split):
  408. # Don't add a newline if the token cannot be split.
  409. return count
  410. if not newline and must_split:
  411. # Don't add a token we must split but where we aren't splitting.
  412. return count
  413. node = _StateNode(previous_node.state, newline, previous_node)
  414. penalty += node.state.AddTokenToState(
  415. newline=newline, dry_run=True, must_split=must_split)
  416. heapq.heappush(p_queue, _QueueItem(_OrderedPenalty(penalty, count), node))
  417. return count + 1
  418. def _ReconstructPath(initial_state, current):
  419. """Reconstruct the path through the queue with lowest penalty.
  420. Arguments:
  421. initial_state: (format_decision_state.FormatDecisionState) The initial state
  422. to start the search from.
  423. current: (_StateNode) The node in the decision graph that is the end point
  424. of the path with the least penalty.
  425. """
  426. path = collections.deque()
  427. while current.previous:
  428. path.appendleft(current)
  429. current = current.previous
  430. for node in path:
  431. initial_state.AddTokenToState(newline=node.newline, dry_run=False)
  432. NESTED_DEPTH = []
  433. def _FormatFirstToken(first_token, indent_depth, prev_line, final_lines):
  434. """Format the first token in the logical line.
  435. Add a newline and the required indent before the first token of the logical
  436. line.
  437. Arguments:
  438. first_token: (format_token.FormatToken) The first token in the logical line.
  439. indent_depth: (int) The line's indentation depth.
  440. prev_line: (list of logical_line.LogicalLine) The logical line previous to
  441. this line.
  442. final_lines: (list of logical_line.LogicalLine) The logical lines that have
  443. already been processed.
  444. """
  445. global NESTED_DEPTH
  446. while NESTED_DEPTH and NESTED_DEPTH[-1] > indent_depth:
  447. NESTED_DEPTH.pop()
  448. first_nested = False
  449. if _IsClassOrDef(first_token):
  450. if not NESTED_DEPTH:
  451. NESTED_DEPTH = [indent_depth]
  452. elif NESTED_DEPTH[-1] < indent_depth:
  453. first_nested = True
  454. NESTED_DEPTH.append(indent_depth)
  455. first_token.AddWhitespacePrefix(
  456. _CalculateNumberOfNewlines(first_token, indent_depth, prev_line,
  457. final_lines, first_nested),
  458. indent_level=indent_depth)
  459. NO_BLANK_LINES = 1
  460. ONE_BLANK_LINE = 2
  461. TWO_BLANK_LINES = 3
  462. def _IsClassOrDef(tok):
  463. if tok.value in {'class', 'def', '@'}:
  464. return True
  465. return (tok.next_token and tok.value == 'async' and
  466. tok.next_token.value == 'def')
  467. def _CalculateNumberOfNewlines(first_token, indent_depth, prev_line,
  468. final_lines, first_nested):
  469. """Calculate the number of newlines we need to add.
  470. Arguments:
  471. first_token: (format_token.FormatToken) The first token in the logical
  472. line.
  473. indent_depth: (int) The line's indentation depth.
  474. prev_line: (list of logical_line.LogicalLine) The logical line previous to
  475. this line.
  476. final_lines: (list of logical_line.LogicalLine) The logical lines that have
  477. already been processed.
  478. first_nested: (boolean) Whether this is the first nested class or function.
  479. Returns:
  480. The number of newlines needed before the first token.
  481. """
  482. # TODO(morbo): Special handling for imports.
  483. # TODO(morbo): Create a knob that can tune these.
  484. if prev_line is None:
  485. # The first line in the file. Don't add blank lines.
  486. # FIXME(morbo): Is this correct?
  487. if first_token.newlines is not None:
  488. first_token.newlines = None
  489. return 0
  490. if first_token.is_docstring:
  491. if (prev_line.first.value == 'class' and
  492. style.Get('BLANK_LINE_BEFORE_CLASS_DOCSTRING')):
  493. # Enforce a blank line before a class's docstring.
  494. return ONE_BLANK_LINE
  495. elif (prev_line.first.value.startswith('#') and
  496. style.Get('BLANK_LINE_BEFORE_MODULE_DOCSTRING')):
  497. # Enforce a blank line before a module's docstring.
  498. return ONE_BLANK_LINE
  499. # The docstring shouldn't have a newline before it.
  500. return NO_BLANK_LINES
  501. if first_token.is_name and not indent_depth:
  502. if prev_line.first.value in {'from', 'import'}:
  503. # Support custom number of blank lines between top-level imports and
  504. # variable definitions.
  505. return 1 + style.Get(
  506. 'BLANK_LINES_BETWEEN_TOP_LEVEL_IMPORTS_AND_VARIABLES')
  507. prev_last_token = prev_line.last
  508. if prev_last_token.is_docstring:
  509. if (not indent_depth and first_token.value in {'class', 'def', 'async'}):
  510. # Separate a class or function from the module-level docstring with
  511. # appropriate number of blank lines.
  512. return 1 + style.Get('BLANK_LINES_AROUND_TOP_LEVEL_DEFINITION')
  513. if (first_nested and
  514. not style.Get('BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF') and
  515. _IsClassOrDef(first_token)):
  516. first_token.newlines = None
  517. return NO_BLANK_LINES
  518. if _NoBlankLinesBeforeCurrentToken(prev_last_token.value, first_token,
  519. prev_last_token):
  520. return NO_BLANK_LINES
  521. else:
  522. return ONE_BLANK_LINE
  523. if _IsClassOrDef(first_token):
  524. # TODO(morbo): This can go once the blank line calculator is more
  525. # sophisticated.
  526. if not indent_depth:
  527. # This is a top-level class or function.
  528. is_inline_comment = prev_last_token.whitespace_prefix.count('\n') == 0
  529. if (not prev_line.disable and prev_last_token.is_comment and
  530. not is_inline_comment):
  531. # This token follows a non-inline comment.
  532. if _NoBlankLinesBeforeCurrentToken(prev_last_token.value, first_token,
  533. prev_last_token):
  534. # Assume that the comment is "attached" to the current line.
  535. # Therefore, we want two blank lines before the comment.
  536. index = len(final_lines) - 1
  537. while index > 0:
  538. if not final_lines[index - 1].is_comment:
  539. break
  540. index -= 1
  541. if final_lines[index - 1].first.value == '@':
  542. final_lines[index].first.AdjustNewlinesBefore(NO_BLANK_LINES)
  543. else:
  544. prev_last_token.AdjustNewlinesBefore(
  545. 1 + style.Get('BLANK_LINES_AROUND_TOP_LEVEL_DEFINITION'))
  546. if first_token.newlines is not None:
  547. first_token.newlines = None
  548. return NO_BLANK_LINES
  549. elif _IsClassOrDef(prev_line.first):
  550. if first_nested and not style.Get(
  551. 'BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF'):
  552. first_token.newlines = None
  553. return NO_BLANK_LINES
  554. # Calculate how many newlines were between the original lines. We want to
  555. # retain that formatting if it doesn't violate one of the style guide rules.
  556. if first_token.is_comment:
  557. first_token_lineno = first_token.lineno - first_token.value.count('\n')
  558. else:
  559. first_token_lineno = first_token.lineno
  560. prev_last_token_lineno = prev_last_token.lineno
  561. if prev_last_token.is_multiline_string:
  562. prev_last_token_lineno += prev_last_token.value.count('\n')
  563. if first_token_lineno - prev_last_token_lineno > 1:
  564. return ONE_BLANK_LINE
  565. return NO_BLANK_LINES
  566. def _SingleOrMergedLines(lines):
  567. """Generate the lines we want to format.
  568. Arguments:
  569. lines: (list of logical_line.LogicalLine) Lines we want to format.
  570. Yields:
  571. Either a single line, if the current line cannot be merged with the
  572. succeeding line, or the next two lines merged into one line.
  573. """
  574. index = 0
  575. last_was_merged = False
  576. while index < len(lines):
  577. if lines[index].disable:
  578. line = lines[index]
  579. index += 1
  580. while index < len(lines):
  581. column = line.last.column + 2
  582. if lines[index].lineno != line.lineno:
  583. break
  584. if line.last.value != ':':
  585. leaf = pytree.Leaf(
  586. type=token.SEMI, value=';', context=('', (line.lineno, column)))
  587. line.AppendToken(
  588. format_token.FormatToken(leaf, pytree_utils.NodeName(leaf)))
  589. for tok in lines[index].tokens:
  590. line.AppendToken(tok)
  591. index += 1
  592. yield line
  593. elif line_joiner.CanMergeMultipleLines(lines[index:], last_was_merged):
  594. # TODO(morbo): This splice is potentially very slow. Come up with a more
  595. # performance-friendly way of determining if two lines can be merged.
  596. next_line = lines[index + 1]
  597. for tok in next_line.tokens:
  598. lines[index].AppendToken(tok)
  599. if (len(next_line.tokens) == 1 and next_line.first.is_multiline_string):
  600. # This may be a multiline shebang. In that case, we want to retain the
  601. # formatting. Otherwise, it could mess up the shell script's syntax.
  602. lines[index].disable = True
  603. yield lines[index]
  604. index += 2
  605. last_was_merged = True
  606. else:
  607. yield lines[index]
  608. index += 1
  609. last_was_merged = False
  610. def _NoBlankLinesBeforeCurrentToken(text, cur_token, prev_token):
  611. """Determine if there are no blank lines before the current token.
  612. The previous token is a docstring or comment. The prev_token_lineno is the
  613. start of the text of that token. Counting the number of newlines in its text
  614. gives us the extent and thus where the line number of the end of the
  615. docstring or comment. After that, we just compare it to the current token's
  616. line number to see if there are blank lines between them.
  617. Arguments:
  618. text: (unicode) The text of the docstring or comment before the current
  619. token.
  620. cur_token: (format_token.FormatToken) The current token in the logical line.
  621. prev_token: (format_token.FormatToken) The previous token in the logical
  622. line.
  623. Returns:
  624. True if there is no blank line before the current token.
  625. """
  626. cur_token_lineno = cur_token.lineno
  627. if cur_token.is_comment:
  628. cur_token_lineno -= cur_token.value.count('\n')
  629. num_newlines = text.count('\n') if not prev_token.is_comment else 0
  630. return prev_token.lineno + num_newlines == cur_token_lineno - 1