Python: select the start-end range of syntax errors
Python 3.10's syntax errors can specify a range. Use this for text editor error selection.
This commit is contained in:
parent
0ce6ed4753
commit
1466f480c4
|
@ -37,12 +37,14 @@
|
|||
|
||||
static void python_script_error_jump_text(Text *text, const char *filepath)
|
||||
{
|
||||
int lineno;
|
||||
int offset;
|
||||
python_script_error_jump(filepath, &lineno, &offset);
|
||||
int lineno, lineno_end;
|
||||
int offset, offset_end;
|
||||
python_script_error_jump(filepath, &lineno, &offset, &lineno_end, &offset_end);
|
||||
if (lineno != -1) {
|
||||
/* select the line with the error */
|
||||
txt_move_to(text, lineno - 1, INT_MAX, false);
|
||||
/* Start at the end so cursor motion that looses the selection,
|
||||
* leaves the cursor from the most useful place.
|
||||
* Also, the end can't always be set, so don't give it priority. */
|
||||
txt_move_to(text, lineno_end - 1, offset_end, false);
|
||||
txt_move_to(text, lineno - 1, offset, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ static const char *traceback_filepath(PyTracebackObject *tb, PyObject **coerce)
|
|||
return PyBytes_AS_STRING(*coerce);
|
||||
}
|
||||
|
||||
/* copied from pythonrun.c, 3.4.0 */
|
||||
/* copied from pythonrun.c, 3.10.0 */
|
||||
_Py_static_string(PyId_string, "<string>");
|
||||
|
||||
static int parse_syntax_error(PyObject *err,
|
||||
|
@ -32,14 +32,18 @@ static int parse_syntax_error(PyObject *err,
|
|||
PyObject **filename,
|
||||
int *lineno,
|
||||
int *offset,
|
||||
int *end_lineno,
|
||||
int *end_offset,
|
||||
PyObject **text)
|
||||
{
|
||||
long hold;
|
||||
Py_ssize_t hold;
|
||||
PyObject *v;
|
||||
_Py_IDENTIFIER(msg);
|
||||
_Py_IDENTIFIER(filename);
|
||||
_Py_IDENTIFIER(lineno);
|
||||
_Py_IDENTIFIER(offset);
|
||||
_Py_IDENTIFIER(end_lineno);
|
||||
_Py_IDENTIFIER(end_offset);
|
||||
_Py_IDENTIFIER(text);
|
||||
|
||||
*message = NULL;
|
||||
|
@ -71,7 +75,7 @@ static int parse_syntax_error(PyObject *err,
|
|||
if (!v) {
|
||||
goto finally;
|
||||
}
|
||||
hold = PyLong_AsLong(v);
|
||||
hold = PyLong_AsSsize_t(v);
|
||||
Py_DECREF(v);
|
||||
if (hold < 0 && PyErr_Occurred()) {
|
||||
goto finally;
|
||||
|
@ -87,7 +91,7 @@ static int parse_syntax_error(PyObject *err,
|
|||
Py_DECREF(v);
|
||||
}
|
||||
else {
|
||||
hold = PyLong_AsLong(v);
|
||||
hold = PyLong_AsSsize_t(v);
|
||||
Py_DECREF(v);
|
||||
if (hold < 0 && PyErr_Occurred()) {
|
||||
goto finally;
|
||||
|
@ -95,6 +99,49 @@ static int parse_syntax_error(PyObject *err,
|
|||
*offset = (int)hold;
|
||||
}
|
||||
|
||||
if (Py_TYPE(err) == (PyTypeObject *)PyExc_SyntaxError) {
|
||||
v = _PyObject_GetAttrId(err, &PyId_end_lineno);
|
||||
if (!v) {
|
||||
PyErr_Clear();
|
||||
*end_lineno = *lineno;
|
||||
}
|
||||
else if (v == Py_None) {
|
||||
*end_lineno = *lineno;
|
||||
Py_DECREF(v);
|
||||
}
|
||||
else {
|
||||
hold = PyLong_AsSsize_t(v);
|
||||
Py_DECREF(v);
|
||||
if (hold < 0 && PyErr_Occurred()) {
|
||||
goto finally;
|
||||
}
|
||||
*end_lineno = hold;
|
||||
}
|
||||
|
||||
v = _PyObject_GetAttrId(err, &PyId_end_offset);
|
||||
if (!v) {
|
||||
PyErr_Clear();
|
||||
*end_offset = -1;
|
||||
}
|
||||
else if (v == Py_None) {
|
||||
*end_offset = -1;
|
||||
Py_DECREF(v);
|
||||
}
|
||||
else {
|
||||
hold = PyLong_AsSsize_t(v);
|
||||
Py_DECREF(v);
|
||||
if (hold < 0 && PyErr_Occurred()) {
|
||||
goto finally;
|
||||
}
|
||||
*end_offset = hold;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* `SyntaxError` subclasses. */
|
||||
*end_lineno = *lineno;
|
||||
*end_offset = -1;
|
||||
}
|
||||
|
||||
v = _PyObject_GetAttrId(err, &PyId_text);
|
||||
if (!v) {
|
||||
goto finally;
|
||||
|
@ -115,7 +162,8 @@ finally:
|
|||
}
|
||||
/* end copied function! */
|
||||
|
||||
void python_script_error_jump(const char *filepath, int *r_lineno, int *r_offset)
|
||||
void python_script_error_jump(
|
||||
const char *filepath, int *r_lineno, int *r_offset, int *r_lineno_end, int *r_offset_end)
|
||||
{
|
||||
PyObject *exception, *value;
|
||||
PyTracebackObject *tb;
|
||||
|
@ -123,6 +171,9 @@ void python_script_error_jump(const char *filepath, int *r_lineno, int *r_offset
|
|||
*r_lineno = -1;
|
||||
*r_offset = 0;
|
||||
|
||||
*r_lineno_end = -1;
|
||||
*r_offset_end = 0;
|
||||
|
||||
PyErr_Fetch(&exception, &value, (PyObject **)&tb);
|
||||
if (exception == NULL) {
|
||||
return;
|
||||
|
@ -137,7 +188,14 @@ void python_script_error_jump(const char *filepath, int *r_lineno, int *r_offset
|
|||
PyObject *message;
|
||||
PyObject *filepath_exc_py, *text_py;
|
||||
|
||||
if (parse_syntax_error(value, &message, &filepath_exc_py, r_lineno, r_offset, &text_py)) {
|
||||
if (parse_syntax_error(value,
|
||||
&message,
|
||||
&filepath_exc_py,
|
||||
r_lineno,
|
||||
r_offset,
|
||||
r_lineno_end,
|
||||
r_offset_end,
|
||||
&text_py)) {
|
||||
const char *filepath_exc = PyUnicode_AsUTF8(filepath_exc_py);
|
||||
/* python adds a '/', prefix, so check for both */
|
||||
if ((BLI_path_cmp(filepath_exc, filepath) == 0) ||
|
||||
|
@ -170,7 +228,7 @@ void python_script_error_jump(const char *filepath, int *r_lineno, int *r_offset
|
|||
Py_DECREF(coerce);
|
||||
|
||||
if (match) {
|
||||
*r_lineno = tb->tb_lineno;
|
||||
*r_lineno = *r_lineno_end = tb->tb_lineno;
|
||||
/* used to break here, but better find the inner most line */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
void python_script_error_jump(const char *filepath, int *r_lineno, int *r_offset);
|
||||
void python_script_error_jump(
|
||||
const char *filepath, int *r_lineno, int *r_offset, int *r_lineno_end, int *r_offset_end);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue