@@ -90,27 +90,41 @@ void SwiftASTManipulator::WrapExpression(
9090__builtin_logger_initialize()
9191)" ;
9292
93- // The debug function declarations need only be declared once per session - on the first REPL call.
94- // This code assumes that the first call is the first REPL call; don't call playground once then playground || repl again
93+ // The debug function declarations need only be declared once per session -
94+ // on the first REPL call. This code assumes that the first call is the
95+ // first REPL call; don't call playground once then playground || repl
96+ // again
9597 bool first_expression = options.GetPreparePlaygroundStubFunctions ();
9698
97- const char *playground_prefix = first_expression ? playground_logger_declarations : " " ;
99+ const char *playground_prefix =
100+ first_expression ? playground_logger_declarations : " " ;
98101
99102 if (pound_file && pound_line) {
100103 wrapped_stream.Printf (" %s#sourceLocation(file: \" %s\" , line: %u)\n %s\n " ,
101104 playground_prefix, pound_file, pound_line,
102105 orig_text);
103106 } else {
104- // In 2017+, xcode playgrounds send orig_text that starts with a module loading prefix (not the above prefix), then a sourceLocation specifier that indicates the page name, and then the page body text.
105- // The first_body_line mechanism in this function cannot be used to compensate for the playground_prefix added here, since it incorrectly continues to apply even after sourceLocation directives are read frmo the orig_text.
106- // To make sure playgrounds work correctly whether or not they supply their own sourceLocation, create a dummy sourceLocation here with a fake filename that starts counting the first line of orig_text as line 1.
107+ // In 2017+, xcode playgrounds send orig_text that starts with a module
108+ // loading prefix (not the above prefix), then a sourceLocation specifier
109+ // that indicates the page name, and then the page body text. The
110+ // first_body_line mechanism in this function cannot be used to
111+ // compensate for the playground_prefix added here, since it incorrectly
112+ // continues to apply even after sourceLocation directives are read from
113+ // the orig_text. To make sure playgrounds work correctly whether or not
114+ // they supply their own sourceLocation, create a dummy sourceLocation
115+ // here with a fake filename that starts counting the first line of
116+ // orig_text as line 1.
107117 wrapped_stream.Printf (" %s#sourceLocation(file: \" %s\" , line: %u)\n %s\n " ,
108118 playground_prefix, " Playground.swift" , 1 ,
109119 orig_text);
110120 }
111121 first_body_line = 1 ;
112122 return ;
113- } else if (repl) { // repl but not playground.
123+ }
124+
125+ assert (!playground && " Playground mode not expected" );
126+
127+ if (repl) {
114128 if (pound_file && pound_line) {
115129 wrapped_stream.Printf (" #sourceLocation(file: \" %s\" , line: %u)\n %s\n " ,
116130 llvm::sys::path::filename (pound_file).str ().c_str (),
@@ -122,87 +136,85 @@ __builtin_logger_initialize()
122136 return ;
123137 }
124138
125- std::string expr_source_path ;
139+ assert (!playground && !repl && " Playground/REPL mode not expected " ) ;
126140
127141 if (pound_file && pound_line) {
128142 fixed_text.Printf (" #sourceLocation(file: \" %s\" , line: %u)\n %s\n " ,
129143 pound_file, pound_line, orig_text);
130144 text = fixed_text.GetString ().data ();
131145 } else if (generate_debug_info) {
146+ std::string expr_source_path;
132147 if (SwiftASTManipulator::SaveExpressionTextToTempFile (orig_text, options,
133- expr_source_path)) {
148+ expr_source_path)) {
134149 fixed_text.Printf (" #sourceLocation(file: \" %s\" , line: 1)\n %s\n " ,
135150 expr_source_path.c_str (), orig_text);
136151 text = fixed_text.GetString ().data ();
137152 }
138153 }
139154
140155 // Note: All the wrapper functions we make are marked with the
141- // @LLDBDebuggerFunction macro so that the compiler
142- // can do whatever special treatment it need to do on them. If you add new
143- // variants be sure to mark them this way.
144- // Also, any function that might end up being in an extension of swift class
145- // needs to be marked final, since otherwise
146- // the compiler might try to dispatch them dynamically, which it can't do
147- // correctly for these functions.
148-
149- llvm::SmallString<32 > buffer;
150- llvm::raw_svector_ostream os (buffer);
156+ // @LLDBDebuggerFunction macro so that the compiler can do whatever special
157+ // treatment it need to do on them. If you add new variants be sure to mark
158+ // them this way. Also, any function that might end up being in an extension
159+ // of swift class needs to be marked final, since otherwise the compiler
160+ // might try to dispatch them dynamically, which it can't do correctly for
161+ // these functions.
162+
163+ std::string availability = " " ;
151164 if (!os_version.empty ())
152- os << " @available(" << os_version << " , *)" ;
153- std::string availability = os.str ();
165+ availability = (llvm::Twine (" @available(" ) + os_version + " , *)" ).str ();
154166
155167 StreamString wrapped_expr_text;
156- wrapped_expr_text.Printf (" do\n "
157- " {\n "
158- " %s%s%s\n " // Don't indent the code so error columns
159- // match up with errors from compiler
160- " }\n "
161- " catch (let __lldb_tmp_error)\n "
162- " {\n "
163- " var %s = __lldb_tmp_error\n "
164- " }\n " ,
168+
169+ // Avoid indenting user code: this makes column information from compiler
170+ // errors match up with what the user typed.
171+ wrapped_expr_text.Printf (R"(
172+ do {
173+ %s%s%s
174+ } catch (let __lldb_tmp_error) {
175+ var %s = __lldb_tmp_error
176+ }
177+ )" ,
165178 GetUserCodeStartMarker (), text,
166179 GetUserCodeEndMarker (), GetErrorName ());
167180
168- if (needs_object_ptr | static_method) {
181+ if (needs_object_ptr || static_method) {
169182 const char *func_decorator = " " ;
170183 if (static_method) {
171184 if (is_class)
172185 func_decorator = " final class" ;
173186 else
174187 func_decorator = " static" ;
175- } else if (is_class &&
176- !(weak_self)) {
188+ } else if (is_class && !weak_self) {
177189 func_decorator = " final" ;
178190 } else {
179191 func_decorator = " mutating" ;
180192 }
181193
182194 const char *optional_extension =
183- ( weak_self)
184- ? " Swift.Optional where Wrapped == "
185- : " " ;
186-
187- wrapped_stream. Printf (
188- " extension %s$__lldb_context { \n "
189- " @LLDBDebuggerFunction %s \n "
190- " %s func $__lldb_wrapped_expr_%u(_ $__lldb_arg : "
191- " UnsafeMutablePointer<Any>) { \n "
192- " %s " // This is the expression text (with newlines).
193- " } \n "
194- " } \n "
195- " %s \n "
196- " func $__lldb_expr(_ $__lldb_arg : UnsafeMutablePointer<Any>) { \n "
197- " do { \n "
198- " $__lldb_injected_self.$__lldb_wrapped_expr_%u( \n "
199- " $__lldb_arg \n "
200- " ) \n "
201- " } \n "
202- " } \n " ,
203- optional_extension, availability. c_str (), func_decorator,
204- current_counter, wrapped_expr_text.GetData (), availability.c_str (),
205- current_counter);
195+ weak_self ? " Swift.Optional where Wrapped == " : " " ;
196+
197+ // The expression text is inserted into the body of $__lldb_wrapped_expr_%u.
198+ wrapped_stream. Printf ( R"(
199+ extension %s$__lldb_context {
200+ @LLDBDebuggerFunction %s
201+ %s func $__lldb_wrapped_expr_%u(_ $__lldb_arg : UnsafeMutablePointer<Any>) {
202+ %s
203+ }
204+ }
205+ %s
206+ func $__lldb_expr(_ $__lldb_arg : UnsafeMutablePointer<Any>) {
207+ do {
208+ $__lldb_injected_self.$__lldb_wrapped_expr_%u(
209+ $__lldb_arg
210+ )
211+ }
212+ }
213+ )" ,
214+ optional_extension, availability. c_str () ,
215+ func_decorator, current_counter ,
216+ wrapped_expr_text.GetData (), availability.c_str (),
217+ current_counter);
206218
207219 first_body_line = 5 ;
208220 } else {
0 commit comments