def get_tracked():
    x = tracked # $tracked
    return x # $tracked

def use_tracked_foo(x): # $tracked
    do_stuff(x) # $tracked

def foo():
    use_tracked_foo(
        get_tracked() # $tracked
    )

def use_tracked_bar(x): # $tracked
    do_stuff(x) # $tracked

def bar():
    x = get_tracked() # $tracked
    use_tracked_bar(x) # $tracked

def use_tracked_baz(x): # $tracked
    do_stuff(x) # $tracked

def baz():
    x = tracked # $tracked
    use_tracked_baz(x) # $tracked

def id(x): # $tracked
    return x # $tracked

def use_tracked_quux(x): # $ MISSING: tracked
    do_stuff(y) # call after return -- not tracked in here.

def quux():
    x = tracked # $tracked
    y = id(x) # $tracked
    use_tracked_quux(y) # not tracked out of call to id.

g = None

def write_g(x): # $tracked
    global g
    g = x # $tracked

def use_g():
    do_stuff(g) # $tracked

def global_var_write_test():
    x = tracked # $tracked
    write_g(x) # $tracked
    use_g()

def test_import():
    import mymodule
    mymodule.x # $tracked
    y = mymodule.func() # $tracked
    y # $tracked
    mymodule.z # $tracked

# ------------------------------------------------------------------------------

def expects_int(x): # $int
    do_int_stuff(x) # $int

def expects_string(x): # $str
    do_string_stuff(x) # $str

def redefine_test():
    x = int(5) # $int
    expects_int(x) # $int
    x = str("Hello") # $str
    expects_string(x) # $str

# ------------------------------------------------------------------------------
# Tracking of self in methods
# ------------------------------------------------------------------------------

class Foo(object):

    def meth1(self):
        do_stuff(self)

    def meth2(self): # $ MISSING: tracked_self
        do_stuff(self) # $ MISSING: tracked_self

    def meth3(self): # $ MISSING: tracked_self
        do_stuff(self) # $ MISSING: tracked_self


class Bar(Foo):

    def meth1(self): # $ tracked_self
        do_stuff(self) # $ tracked_self

    def meth2(self):
        do_stuff(self)

    def meth3(self):
        do_stuff(self)

    def track_self(self): # $ tracked_self
        self.meth1() # $ tracked_self
        super().meth2()
        super(Bar, self).foo3() # $ tracked_self

# ------------------------------------------------------------------------------
# Tracking of attribute lookup after "long" import chain
# ------------------------------------------------------------------------------

def test_long_import_chain():
    import foo.bar
    foo.baz
    x = foo.bar.baz # $ tracked_foo_bar_baz
    do_stuff(x) # $ tracked_foo_bar_baz

    class Example(foo.bar.baz): # $ tracked_foo_bar_baz
        pass


def test_long_import_chain_full_path():
    from foo.bar import baz # $ tracked_foo_bar_baz
    x = baz # $ tracked_foo_bar_baz
    do_stuff(x) # $ tracked_foo_bar_baz

@@ -1105,16 +1105,812 @@
 racked%0A%0A
+%0Adef to_inner_scope():%0A    x = tracked # $tracked%0A    def foo():%0A        y = x # $ MISSING: tracked%0A        return y # $ MISSING: tracked%0A    also_x = foo() # $ MISSING: tracked%0A    print(also_x) # $ MISSING: tracked%0A%0A%0Adef my_decorator(func):%0A    # This part doesn't make any sense in a normal decorator, but just shows how we%0A    # handle type-tracking%0A%0A    func() # $tracked%0A%0A    def wrapper():%0A        print(%22before function call%22)%0A        val = func() # $ MISSING: tracked%0A        print(%22after function call%22)%0A        return val # $ MISSING: tracked%0A    return wrapper%0A%0A@my_decorator%0Adef get_tracked2():%0A    return tracked # $tracked%0A%0A@my_decorator%0Adef unrelated_func():%0A    return %22foo%22%0A%0Adef use_funcs_with_decorators():%0A    x = get_tracked2() # $ MISSING: tracked%0A    y = unrelated_func()%0A%0A
 # ------

Add test for type-tracking through decorators