LibCST/libcst/codegen/transforms.py
Jennifer Taylor 48ba3b0849 Remove parsing Subscript slice directly into Index/Slice.
This makes sure we always wrap elements in a SubscriptElement, even when there
is only one element. This makes things more regular while still being backwards
compatible with existing creation. The meat of this is in two halves, which can't
be split due to not wanting to break the build between commits. The first half
is just the changes to the parser and updates to tests. This includes a test to
be sure we can still render code that uses old construction types. The second half
is changes to codegen which made assumptions about `Subscript` and demonstrates
the need to make this change in the first place. This includes a fix to
`CSTNode.with_deep_changes` type to make it more correct and also more usable in
transforms without additional type assertions.
2019-10-18 13:40:10 -07:00

45 lines
2 KiB
Python

# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
# This holds a series of transforms that help prettify generated code.
# The design is such that any of them could be left out and the code
# in question will still be correct, but possibly uglier to look at.
# Great care should be taken to include only transforms that do not
# affect the behavior of generated code, only the style for readability.
# As a result, since these can be skipped without harm, it is okay to
# use features such as matchers which rely on previously generated
# code to function.
# pyre-strict
import libcst as cst
import libcst.matchers as m
class SimplifyUnionsTransformer(m.MatcherDecoratableTransformer):
@m.leave(m.Subscript(m.Name("Union")))
def _leave_union(
self, original_node: cst.Subscript, updated_node: cst.Subscript
) -> cst.BaseExpression:
slc = updated_node.slice
# TODO: We can remove the instance check after ExtSlice is deprecated.
if isinstance(slc, (cst.Slice, cst.Index)):
# This is deprecated, so lets not support it.
raise Exception("Unexpected Slice in Union!")
if len(slc) == 1:
# This is a Union[SimpleType,] which is equivalent to
# just SimpleType
return cst.ensure_type(slc[0].slice, cst.Index).value
return updated_node
class DoubleQuoteForwardRefsTransformer(m.MatcherDecoratableTransformer):
@m.call_if_inside(m.Annotation())
def leave_SimpleString(
self, original_node: cst.SimpleString, updated_node: cst.SimpleString
) -> cst.SimpleString:
# For prettiness, convert all single-quoted forward refs to double-quoted.
if updated_node.value.startswith("'") and updated_node.value.endswith("'"):
return updated_node.with_changes(value=f'"{updated_node.value[1:-1]}"')
return updated_node