File: TestFixIts.py

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (184 lines) | stat: -rw-r--r-- 7,815 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
"""
Test calling an expression with errors that a FixIt can fix.
"""

import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil


class ExprCommandWithFixits(TestBase):
    def test_with_dummy_target(self):
        """Test calling expressions in the dummy target with errors that can be fixed by the FixIts."""

        # Enable fix-its as they were intentionally disabled by TestBase.setUp.
        self.runCmd("settings set target.auto-apply-fixits true")

        ret_val = lldb.SBCommandReturnObject()
        result = self.dbg.GetCommandInterpreter().HandleCommand(
            "expression ((1 << 16) - 1))", ret_val
        )
        self.assertEqual(
            result, lldb.eReturnStatusSuccessFinishResult, ret_val.GetError()
        )
        self.assertIn(
            "Evaluated this expression after applying Fix-It(s):", ret_val.GetError()
        )

    def test_with_target(self):
        """Test calling expressions with errors that can be fixed by the FixIts."""
        self.build()
        (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(
            self, "Stop here to evaluate expressions", lldb.SBFileSpec("main.cpp")
        )

        options = lldb.SBExpressionOptions()
        options.SetAutoApplyFixIts(True)

        top_level_options = lldb.SBExpressionOptions()
        top_level_options.SetAutoApplyFixIts(True)
        top_level_options.SetTopLevel(True)

        frame = self.thread.GetFrameAtIndex(0)

        # Try with one error:
        value = frame.EvaluateExpression("my_pointer.first", options)
        self.assertTrue(value.IsValid())
        self.assertSuccess(value.GetError())
        self.assertEqual(value.GetValueAsUnsigned(), 10)

        # Try with one error in a top-level expression.
        # The Fix-It changes "ptr.m" to "ptr->m".
        expr = "struct MyTy { int m; }; MyTy x; MyTy *ptr = &x; int m = ptr.m;"
        value = frame.EvaluateExpression(expr, top_level_options)
        # A successfully parsed top-level expression will yield an
        # unknown error . If a parsing error would have happened we
        # would get a different error kind, so let's check the error
        # kind here.
        self.assertEqual(value.GetError().GetCString(), "unknown error")

        # Try with two errors:
        two_error_expression = "my_pointer.second->a"
        value = frame.EvaluateExpression(two_error_expression, options)
        self.assertTrue(value.IsValid())
        self.assertSuccess(value.GetError())
        self.assertEqual(value.GetValueAsUnsigned(), 20)

        # Try a Fix-It that is stored in the 'note:' diagnostic of an error.
        # The Fix-It here is adding parantheses around the ToStr parameters.
        fixit_in_note_expr = "#define ToStr(x) #x\nToStr(0 {, })"
        value = frame.EvaluateExpression(fixit_in_note_expr, options)
        self.assertTrue(value.IsValid())
        self.assertSuccess(value.GetError())
        self.assertEqual(value.GetSummary(), '"(0 {, })"')

        # Now turn off the fixits, and the expression should fail:
        options.SetAutoApplyFixIts(False)
        value = frame.EvaluateExpression(two_error_expression, options)
        self.assertTrue(value.IsValid())
        self.assertTrue(value.GetError().Fail())
        error_string = value.GetError().GetCString()
        self.assertTrue(
            error_string.find("fixed expression suggested:") != -1, "Fix was suggested"
        )
        self.assertTrue(
            error_string.find("my_pointer->second.a") != -1, "Fix was right"
        )

    def test_with_target_error_applies_fixit(self):
        """Check that applying a Fix-it which fails to execute correctly still
        prints that the Fix-it was applied."""
        self.build()
        (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(
            self, "Stop here to evaluate expressions", lldb.SBFileSpec("main.cpp")
        )
        # Enable fix-its as they were intentionally disabled by TestBase.setUp.
        self.runCmd("settings set target.auto-apply-fixits true")
        ret_val = lldb.SBCommandReturnObject()
        result = self.dbg.GetCommandInterpreter().HandleCommand(
            "expression null_pointer.first", ret_val
        )
        self.assertEqual(result, lldb.eReturnStatusFailed, ret_val.GetError())

        self.assertIn(
            "Evaluated this expression after applying Fix-It(s):", ret_val.GetError()
        )
        self.assertIn("null_pointer->first", ret_val.GetError())

    # The final function call runs into SIGILL on aarch64-linux.
    @expectedFailureAll(
        archs=["aarch64"], oslist=["freebsd", "linux"], bugnumber="llvm.org/pr49407"
    )
    def test_with_multiple_retries(self):
        """Test calling expressions with errors that can be fixed by the FixIts."""
        self.build()
        (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(
            self, "Stop here to evaluate expressions", lldb.SBFileSpec("main.cpp")
        )

        # Test repeatedly applying Fix-Its to expressions and reparsing them.
        multiple_runs_options = lldb.SBExpressionOptions()
        multiple_runs_options.SetAutoApplyFixIts(True)
        multiple_runs_options.SetTopLevel(True)

        frame = self.thread.GetFrameAtIndex(0)

        # An expression that needs two parse attempts with one Fix-It each
        # to be successfully parsed.
        two_runs_expr = """
        struct Data { int m; };

        template<typename T>
        struct S1 : public T {
          using T::TypeDef;
          int f() {
            Data data;
            data.m = 123;
            // The first error as the using above requires a 'typename '.
            // Will trigger a Fix-It that puts 'typename' in the right place.
            typename S1<T>::TypeDef i = &data;
            // i has the type "Data *", so this should be i.m.
            // The second run will change the . to -> via the Fix-It.
            return i.m;
          }
        };

        struct ClassWithTypeDef {
          typedef Data *TypeDef;
        };

        int test_X(int i) {
          S1<ClassWithTypeDef> s1;
          return s1.f();
        }
        """

        # Disable retries which will fail.
        multiple_runs_options.SetRetriesWithFixIts(0)
        value = frame.EvaluateExpression(two_runs_expr, multiple_runs_options)
        errmsg = value.GetError().GetCString()
        self.assertIn("using declaration resolved to type without 'typename'", errmsg)
        self.assertIn("fixed expression suggested:", errmsg)
        self.assertIn("using typename T::TypeDef", errmsg)
        # The second Fix-It shouldn't be suggested here as Clang should have
        # aborted the parsing process.
        self.assertNotIn("i->m", errmsg)

        # Retry once, but the expression needs two retries.
        multiple_runs_options.SetRetriesWithFixIts(1)
        value = frame.EvaluateExpression(two_runs_expr, multiple_runs_options)
        errmsg = value.GetError().GetCString()
        self.assertIn("fixed expression suggested:", errmsg)
        # Both our fixed expressions should be in the suggested expression.
        self.assertIn("using typename T::TypeDef", errmsg)
        self.assertIn("i->m", errmsg)

        # Retry twice, which will get the expression working.
        multiple_runs_options.SetRetriesWithFixIts(2)
        value = frame.EvaluateExpression(two_runs_expr, multiple_runs_options)
        # This error signals success for top level expressions.
        self.assertEqual(value.GetError().GetCString(), "unknown error")

        # Test that the code above compiles to the right thing.
        self.expect_expr("test_X(1)", result_type="int", result_value="123")