@@ -36,6 +36,7 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
36
36
eNotImplemented,
37
37
eNotAllocated,
38
38
eNotCallable,
39
+ eInvalidArgumentCount,
39
40
eValid
40
41
};
41
42
@@ -46,27 +47,48 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
46
47
using namespace python ;
47
48
48
49
std::map<llvm::StringLiteral, AbstractMethodCheckerCases> checker;
49
- #define SET_ERROR_AND_CONTINUE (method_name, error ) \
50
+ #define SET_CASE_AND_CONTINUE (method_name, case ) \
50
51
{ \
51
- checker[method_name] = error ; \
52
+ checker[method_name] = case ; \
52
53
continue ; \
53
54
}
54
55
55
- for (const llvm::StringLiteral &method_name : GetAbstractMethods ()) {
56
+ for (const AbstractMethodRequirement &requirement :
57
+ GetAbstractMethodRequirements ()) {
58
+ llvm::StringLiteral method_name = requirement.name ;
56
59
if (!class_dict.HasKey (method_name))
57
- SET_ERROR_AND_CONTINUE (method_name,
58
- AbstractMethodCheckerCases::eNotImplemented)
60
+ SET_CASE_AND_CONTINUE (method_name,
61
+ AbstractMethodCheckerCases::eNotImplemented)
59
62
auto callable_or_err = class_dict.GetItem (method_name);
60
- if (!callable_or_err)
61
- SET_ERROR_AND_CONTINUE (method_name,
62
- AbstractMethodCheckerCases::eNotAllocated)
63
- if (!PythonCallable::Check (callable_or_err.get ().get ()))
64
- SET_ERROR_AND_CONTINUE (method_name,
65
- AbstractMethodCheckerCases::eNotCallable)
66
- checker[method_name] = AbstractMethodCheckerCases::eValid;
63
+ if (!callable_or_err) {
64
+ llvm::consumeError (callable_or_err.takeError ());
65
+ SET_CASE_AND_CONTINUE (method_name,
66
+ AbstractMethodCheckerCases::eNotAllocated)
67
+ }
68
+
69
+ PythonCallable callable = callable_or_err->AsType <PythonCallable>();
70
+ if (!callable)
71
+ SET_CASE_AND_CONTINUE (method_name,
72
+ AbstractMethodCheckerCases::eNotCallable)
73
+
74
+ if (!requirement.min_arg_count )
75
+ SET_CASE_AND_CONTINUE (method_name, AbstractMethodCheckerCases::eValid)
76
+
77
+ auto arg_info_or_err = callable.GetArgInfo ();
78
+ if (!arg_info_or_err) {
79
+ llvm::consumeError (arg_info_or_err.takeError ());
80
+ SET_CASE_AND_CONTINUE (method_name,
81
+ AbstractMethodCheckerCases::eInvalidArgumentCount)
82
+ }
83
+
84
+ PythonCallable::ArgInfo arg_info = *arg_info_or_err;
85
+ checker[method_name] =
86
+ (requirement.min_arg_count <= arg_info.max_positional_args )
87
+ ? AbstractMethodCheckerCases::eValid
88
+ : AbstractMethodCheckerCases::eInvalidArgumentCount;
67
89
}
68
90
69
- #undef HANDLE_ERROR
91
+ #undef SET_CASE_AND_CONTINUE
70
92
71
93
return checker;
72
94
}
@@ -78,8 +100,11 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
78
100
using namespace python ;
79
101
using Locker = ScriptInterpreterPythonImpl::Locker;
80
102
81
- auto create_error = [](std::string message) {
82
- return llvm::createStringError (llvm::inconvertibleErrorCode (), message);
103
+ Log *log = GetLog (LLDBLog::Script);
104
+ auto create_error = [](llvm::StringRef format, auto &&...ts ) {
105
+ return llvm::createStringError (
106
+ llvm::formatv (format.data (), std::forward<decltype (ts)>(ts)...)
107
+ .str ());
83
108
};
84
109
85
110
bool has_class_name = !class_name.empty ();
@@ -107,16 +132,15 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
107
132
PythonModule::MainModule ().ResolveName <python::PythonDictionary>(
108
133
m_interpreter.GetDictionaryName ());
109
134
if (!dict.IsAllocated ())
110
- return create_error (
111
- llvm::formatv (" Could not find interpreter dictionary: %s" ,
112
- m_interpreter.GetDictionaryName ()));
135
+ return create_error (" Could not find interpreter dictionary: {0}" ,
136
+ m_interpreter.GetDictionaryName ());
113
137
114
138
auto init =
115
139
PythonObject::ResolveNameWithDictionary<python::PythonCallable>(
116
140
class_name, dict);
117
141
if (!init.IsAllocated ())
118
- return create_error (llvm::formatv ( " Could not find script class: {0}" ,
119
- class_name.data () ));
142
+ return create_error (" Could not find script class: {0}" ,
143
+ class_name.data ());
120
144
121
145
std::tuple<Args...> original_args = std::forward_as_tuple (args...);
122
146
auto transformed_args = TransformArgs (original_args);
@@ -186,36 +210,45 @@ class ScriptedPythonInterface : virtual public ScriptedInterface {
186
210
if (!checker_or_err)
187
211
return checker_or_err.takeError ();
188
212
213
+ llvm::Error abstract_method_errors = llvm::Error::success ();
189
214
for (const auto &method_checker : *checker_or_err)
190
215
switch (method_checker.second ) {
191
216
case AbstractMethodCheckerCases::eNotImplemented:
192
- LLDB_LOG (GetLog (LLDBLog::Script),
193
- " Abstract method {0}.{1} not implemented." ,
194
- obj_class_name.GetString (), method_checker.first );
217
+ abstract_method_errors = llvm::joinErrors (
218
+ std::move (abstract_method_errors),
219
+ std::move (create_error (" Abstract method {0}.{1} not implemented." ,
220
+ obj_class_name.GetString (),
221
+ method_checker.first )));
195
222
break ;
196
223
case AbstractMethodCheckerCases::eNotAllocated:
197
- LLDB_LOG (GetLog (LLDBLog::Script),
198
- " Abstract method {0}.{1} not allocated." ,
199
- obj_class_name.GetString (), method_checker.first );
224
+ abstract_method_errors = llvm::joinErrors (
225
+ std::move (abstract_method_errors),
226
+ std::move (create_error (" Abstract method {0}.{1} not allocated." ,
227
+ obj_class_name.GetString (),
228
+ method_checker.first )));
200
229
break ;
201
230
case AbstractMethodCheckerCases::eNotCallable:
202
- LLDB_LOG (GetLog (LLDBLog::Script),
203
- " Abstract method {0}.{1} not callable." ,
204
- obj_class_name.GetString (), method_checker.first );
231
+ abstract_method_errors = llvm::joinErrors (
232
+ std::move (abstract_method_errors),
233
+ std::move (create_error (" Abstract method {0}.{1} not callable." ,
234
+ obj_class_name.GetString (),
235
+ method_checker.first )));
236
+ break ;
237
+ case AbstractMethodCheckerCases::eInvalidArgumentCount:
238
+ abstract_method_errors = llvm::joinErrors (
239
+ std::move (abstract_method_errors),
240
+ std::move (create_error (
241
+ " Abstract method {0}.{1} has unexpected argument count." ,
242
+ obj_class_name.GetString (), method_checker.first )));
205
243
break ;
206
244
case AbstractMethodCheckerCases::eValid:
207
- LLDB_LOG (GetLog (LLDBLog::Script),
208
- " Abstract method {0}.{1} implemented & valid." ,
245
+ LLDB_LOG (log, " Abstract method {0}.{1} implemented & valid." ,
209
246
obj_class_name.GetString (), method_checker.first );
210
247
break ;
211
248
}
212
249
213
- for (const auto &method_checker : *checker_or_err)
214
- if (method_checker.second != AbstractMethodCheckerCases::eValid)
215
- return create_error (
216
- llvm::formatv (" Abstract method {0}.{1} missing. Enable lldb "
217
- " script log for more details." ,
218
- obj_class_name.GetString (), method_checker.first ));
250
+ if (abstract_method_errors)
251
+ return abstract_method_errors;
219
252
220
253
m_object_instance_sp = StructuredData::GenericSP (
221
254
new StructuredPythonObject (std::move (result)));
0 commit comments