Ejemplo n.º 1
0
 def __extract_variable_name_type(self, node: cst.AnnAssign):
     """
     Extracts a variable's identifier name and its type annotation
     """
     return match.extract(
         node,
         match.AnnAssign(  # Annotated Assignment
             target=match.OneOf(
                 match.Name(  # Variable name of assignment (only one)
                     value=match.SaveMatchedNode(  # Save result
                         match.MatchRegex(
                             r'(.)+'),  # Match any string literal
                         "name")),
                 # This extracts variables inside __init__ which typically starts with self (e.g. self.x:int=2)
                 match.Attribute(
                     value=match.Name(value=match.SaveMatchedNode(
                         match.MatchRegex(r'(.)+'),
                         "obj_name"  # Object name
                     )),
                     attr=match.Name(
                         match.SaveMatchedNode(match.MatchRegex(r'(.)+'),
                                               "name")),
                 )),
             annotation=match.SaveMatchedNode(  # Save result
                 match.DoNotCare(),  # Match any string literal
                 "type")))
Ejemplo n.º 2
0
 def test_and_operator_matcher_true(self) -> None:
     # Match on True identifier in roundabout way.
     self.assertTrue(
         matches(cst.Name("True"), m.Name() & m.Name(value=m.MatchRegex(r"True")))
     )
     # Match in a really roundabout way that verifies the __or__ behavior on
     # AllOf itself.
     self.assertTrue(
         matches(
             cst.Name("True"),
             m.Name() & m.Name(value=m.MatchRegex(r"True")) & m.Name("True"),
         )
     )
     # Verify that MatchIfTrue works with __and__ behavior properly.
     self.assertTrue(
         matches(
             cst.Name("True"),
             m.MatchIfTrue(lambda x: isinstance(x, cst.Name))
             & m.Name(value=m.MatchRegex(r"True")),
         )
     )
     self.assertTrue(
         matches(
             cst.Name("True"),
             m.Name(value=m.MatchRegex(r"True"))
             & m.MatchIfTrue(lambda x: isinstance(x, cst.Name)),
         )
     )
Ejemplo n.º 3
0
 def test_and_matcher_true(self) -> None:
     # Match on True identifier in roundabout way.
     self.assertTrue(
         matches(
             cst.Name("True"), m.AllOf(m.Name(), m.Name(value=m.MatchRegex(r"True")))
         )
     )
     self.assertTrue(
         matches(
             cst.Call(
                 func=cst.Name("foo"),
                 args=(
                     cst.Arg(cst.Integer("1")),
                     cst.Arg(cst.Integer("2")),
                     cst.Arg(cst.Integer("3")),
                 ),
             ),
             m.Call(
                 func=m.Name("foo"),
                 args=m.AllOf(
                     (m.Arg(), m.Arg(), m.Arg()),
                     (
                         m.Arg(m.Integer("1")),
                         m.Arg(m.Integer("2")),
                         m.Arg(m.Integer("3")),
                     ),
                 ),
             ),
         )
     )
Ejemplo n.º 4
0
 def test_does_not_match_true(self) -> None:
     # Match on any call that takes one argument that isn't the value None.
     self.assertTrue(
         matches(
             libcst.Call(libcst.Name("foo"),
                         (libcst.Arg(libcst.Name("True")), )),
             m.Call(args=(m.Arg(value=m.DoesNotMatch(m.Name("None"))), )),
         ))
     self.assertTrue(
         matches(
             libcst.Call(libcst.Name("foo"),
                         (libcst.Arg(libcst.Integer("1")), )),
             m.Call(args=(m.DoesNotMatch(m.Arg(m.Name("None"))), )),
         ))
     self.assertTrue(
         matches(
             libcst.Call(libcst.Name("foo"),
                         (libcst.Arg(libcst.Integer("1")), )),
             m.Call(args=m.DoesNotMatch((m.Arg(m.Integer("2")), ))),
         ))
     # Match any call that takes an argument which isn't True or False.
     self.assertTrue(
         matches(
             libcst.Call(libcst.Name("foo"),
                         (libcst.Arg(libcst.Integer("1")), )),
             m.Call(args=(m.Arg(value=m.DoesNotMatch(
                 m.OneOf(m.Name("True"), m.Name("False")))), )),
         ))
     # Match any name node that doesn't match the regex for True
     self.assertTrue(
         matches(
             libcst.Name("False"),
             m.Name(value=m.DoesNotMatch(m.MatchRegex(r"True"))),
         ))
Ejemplo n.º 5
0
    def __extract_variable_name(self, node: cst.AssignTarget):
        extracted_var_names = match.extract(
            node,
            match.AssignTarget(  # Assignment operator
                target=match.OneOf(  # Two cases exist
                    match.Name(  # Single target
                        value=match.SaveMatchedNode(  # Save result
                            match.MatchRegex(
                                r'(.)+'),  # Match any string literal
                            "name")),
                    match.Tuple(  # Multi-target
                        elements=match.SaveMatchedNode(  # Save result
                            match.DoNotCare(),  # Type of list
                            "names")),
                    # This extracts variables inside __init__ without type annotation (e.g. self.x=2)
                    match.Attribute(
                        value=match.Name(value=match.SaveMatchedNode(
                            match.MatchRegex(r'(.)+'),
                            "obj_name"  # Object name
                        )),
                        attr=match.Name(
                            match.SaveMatchedNode(match.MatchRegex(r'(.)+'),
                                                  "name")),
                    ))))

        if extracted_var_names is not None:
            if "name" in extracted_var_names:
                t = self.__get_type_from_metadata(node.target)
                extracted_var_names['type'] = (t, INF_TYPE_ANNOT
                                               if t else UNK_TYPE_ANNOT)
                return extracted_var_names
            elif "names" in extracted_var_names:
                return {
                    'names':
                    self.__extract_names_multi_assign(
                        list(extracted_var_names['names']))
                }
        else:
            return extracted_var_names
Ejemplo n.º 6
0
 def test_does_not_match_operator_true(self) -> None:
     # Match on any call that takes one argument that isn't the value None.
     self.assertTrue(
         matches(
             libcst.Call(libcst.Name("foo"),
                         (libcst.Arg(libcst.Name("True")), )),
             m.Call(args=(m.Arg(value=~m.Name("None")), )),
         ))
     self.assertTrue(
         matches(
             libcst.Call(libcst.Name("foo"),
                         (libcst.Arg(libcst.Integer("1")), )),
             m.Call(args=(~m.Arg(m.Name("None")), )),
         ))
     # Match any call that takes an argument which isn't True or False.
     self.assertTrue(
         matches(
             libcst.Call(libcst.Name("foo"),
                         (libcst.Arg(libcst.Integer("1")), )),
             m.Call(args=(m.Arg(
                 value=~(m.Name("True") | m.Name("False"))), )),
         ))
     self.assertTrue(
         matches(
             libcst.Call(libcst.Name("foo"),
                         (libcst.Arg(libcst.Name("None")), )),
             m.Call(args=(m.Arg(value=(~m.Name("True"))
                                & (~m.Name("False"))), )),
         ))
     # Roundabout way to verify that or operator works with inverted nodes.
     self.assertTrue(
         matches(
             libcst.Call(libcst.Name("foo"),
                         (libcst.Arg(libcst.Name("False")), )),
             m.Call(args=(m.Arg(value=(~m.Name("True"))
                                | (~m.Name("True"))), )),
         ))
     # Roundabout way to verify that inverse operator works properly on AllOf.
     self.assertTrue(
         matches(
             libcst.Call(libcst.Name("foo"),
                         (libcst.Arg(libcst.Integer("1")), )),
             m.Call(args=(m.Arg(value=~(m.Name() & m.Name("True"))), )),
         ))
     # Match any name node that doesn't match the regex for True
     self.assertTrue(
         matches(libcst.Name("False"),
                 m.Name(value=~m.MatchRegex(r"True"))))
Ejemplo n.º 7
0
    def visit_ImportAlias(self, node: cst.ImportAlias):
        """
        Extracts imports.

        Even if an Import has no alias, the Import node will still have an ImportAlias
        with it's real name.
        """
        # Extract information from the Import Alias node.
        # Both the (real) import name and the alias are extracted.
        # Result is returned as a dictionary with a name:node KV pair,
        # and an alias:name KV pair if an alias is present.
        import_info = match.extract(
            node,
            match.ImportAlias(
                asname=match.AsName(  # Attempt to match alias
                    name=match.Name(  # Check for alias name
                        value=match.SaveMatchedNode(  # Save the alias name
                            match.MatchRegex(
                                r'(.)+'),  # Match any string literal
                            "alias"))) | ~match.AsName(),
                # If there is no AsName, we should still match. We negate AsName to and OR to form a tautology.
                name=match.SaveMatchedNode(  # Match & save name of import
                    match.DoNotCare(), "name")))

        # Add import if a name could be extracted.
        if "name" in import_info:
            # Append import name to imports list.
            # We convert the ImportAlias node to the code representation for simplified conversion
            # of multi-level imports (e.g. import.x.y.z)
            # TODO: This might be un-needed after implementing import type extraction change.
            # TODO: So far, no differentiation between import and from imports.
            import_name = self.__convert_node_to_code(import_info["name"])
            import_name = self.__clean_string_whitespace(import_name)
            self.imports.append(import_name)

        if "alias" in import_info:
            import_name = self.__clean_string_whitespace(import_info["alias"])
            self.imports.append(import_name)

        # No need to traverse children, as we already performed the matching.
        return False
Ejemplo n.º 8
0
 def test_does_not_match_operator_false(self) -> None:
     # Match on any call that takes one argument that isn't the value None.
     self.assertFalse(
         matches(
             libcst.Call(libcst.Name("foo"),
                         (libcst.Arg(libcst.Name("None")), )),
             m.Call(args=(m.Arg(value=~m.Name("None")), )),
         ))
     self.assertFalse(
         matches(
             libcst.Call(libcst.Name("foo"),
                         (libcst.Arg(libcst.Integer("1")), )),
             m.Call(args=((~m.Arg(m.Integer("1"))), )),
         ))
     # Match any call that takes an argument which isn't True or False.
     self.assertFalse(
         matches(
             libcst.Call(libcst.Name("foo"),
                         (libcst.Arg(libcst.Name("False")), )),
             m.Call(args=(m.Arg(
                 value=~(m.Name("True") | m.Name("False"))), )),
         ))
     # Roundabout way of verifying ~(x&y) behavior.
     self.assertFalse(
         matches(
             libcst.Call(libcst.Name("foo"),
                         (libcst.Arg(libcst.Name("False")), )),
             m.Call(args=(m.Arg(value=~(m.Name() & m.Name("False"))), )),
         ))
     # Roundabout way of verifying (~x)|(~y) behavior
     self.assertFalse(
         matches(
             libcst.Call(libcst.Name("foo"),
                         (libcst.Arg(libcst.Name("True")), )),
             m.Call(args=(m.Arg(value=(~m.Name("True"))
                                | (~m.Name("True"))), )),
         ))
     # Match any name node that doesn't match the regex for True
     self.assertFalse(
         matches(libcst.Name("True"), m.Name(value=~m.MatchRegex(r"True"))))
Ejemplo n.º 9
0
    def __extract_assign_newtype(self, node: cst.Assign):
        """
        Attempts extracting a NewType declaration from the provided Assign node.

        If the Assign node corresponds to a NewType assignment, the NewType name is
        added to the class definitions of the Visitor.
        """
        # Define matcher to extract NewType assignment
        matcher_newtype = match.Assign(
            targets=[  # Check the assign targets
                match.AssignTarget(  # There should only be one target
                    target=match.Name(  # Check target name
                        value=match.SaveMatchedNode(  # Save target name
                            match.MatchRegex(
                                r'(.)+'),  # Match any string literal
                            "type")))
            ],
            value=match.Call(  # We are examining a function call
                func=match.Name(  # Function must have a name
                    value="NewType"  # Name must be 'NewType'
                ),
                args=[
                    match.Arg(  # Check first argument
                        value=match.SimpleString(
                        )  # First argument must be the name for the type
                    ),
                    match.ZeroOrMore(
                    )  # We allow any number of arguments after by def. of NewType
                ]))

        extracted_type = match.extract(node, matcher_newtype)

        if extracted_type is not None:
            # Append the additional type to the list
            # TODO: Either rename class defs, or create new list for additional types
            self.class_defs.append(extracted_type["type"].strip("\'"))
Ejemplo n.º 10
0
 def test_regex_matcher_false(self) -> None:
     # Fail to match due to incorrect value on Name.
     self.assertFalse(matches(cst.Name("foo"), m.Name(value=m.MatchRegex(r".*a.*"))))
Ejemplo n.º 11
0
 def test_regex_matcher_true(self) -> None:
     # Match based on identical attributes.
     self.assertTrue(matches(cst.Name("foo"), m.Name(value=m.MatchRegex(r".*o.*"))))