martes, 28 de junio de 2016

Errores más a mano en ZinjaI

Estuve implementando algunos cambios en ZinjaI para poder hacer más cosas de las que hago con la lista de warnings y errores que da el compilador. Hasta hace poco, toda la salida se concentraba en el panel de resultados exclusivamente, pero ahora agregué otra forma de ver los errores que puede ser mucho más cómoda para pequeños programas autocontenidos, como los que hacemos en el aula en las clases de programación.

Hasta la última versión estable, la poca inteligencia que aplicaba ZinjaI para trabajar sobre la salida del compilador estaba destina a separar los verdaderos mensajes de error de sus notas y su información de contexto, y simplificar un poco los mensajes que incluían templates. Lo primero era para colocar como items de primer nivel en el árbol del panel de resultados a los verdaderos mensajes de errores, en un segundo nivel, como hijos de los primeros, a las notas, y directamente (y arbitrariamente) ocultar la información adicional del contexto.

El error original hablaba de std::basic_string<char> y std::basic_string<_CharT, _Traits, _Alloc>

El tema de los templates responde a mostrar los tipos o prototipos especializados (gcc da algo como "foo<T>() con T = int" y ZinjaI muestra "foo<int>()") y reemplazar algunos tipos base que usa internamente la biblioteca estándar para esconder cierta complejidad ("detalles" como std::basic_string y los allocators). Lo primero ha quedado algo obsoleto gracias a llvm+clang, que se ha caracterizado desde el comienzo por sus (más) claros mensajes de error, y ha obligado a gcc a mejorar también.

La nueva funcionalidad, que ya tengo lista para la próxima versión, es la que marca en el margen izquierdo las lineas que generan errores y/o warnings, y permite ver los mensajes de error simplificados (más todavía) con solo colocar el mouse sobre los mismos. Y esto no es tan trivial como analizar cada linea de salida del compilador y asignarla a un marcador en el margen (como hace por ejemplo el sitio cpp.sh, que fue el disparador de esta idea). Además de distinguir errores de notas e información de contexto, para mostrar todo lo relacionado a un error como una sola cosa (en eso falla cpp.sh), hay también casos donde el error no está donde el compilador dice que está.

Por ejemplo, si invoco a una función genérica y la especialización falla porque la función quiere cierto método del tipo genérico que en ese caso no tiene... ¿es error de la función por requerir ese método? ¿o del programa cliente por pasarle un tipo que lo no tiene? Gcc marcará el problema dentro de la función, porque es donde lo detecta, pero el error puede ser del programa cliente (el ejemplo clásico es crear un arreglo de structs y pasarselo a std::sort). ZinjaI, por las dudas, además de marcar el error donde gcc lo detecta, mostrará también una versión reducida del mismo en el punto de la llamada del progama cliente que deriva finalmente en ese error. Algo similar aplica, por ejemplo, para las funciones de preprocesador.

gcc marca estos dos errores dentro de la implementación de std::sort, y entre los dos generan 24 lineas
de errores y notas. ZinjaI extrae "lo importante" de todo eso y lo muestra en el lugar de la llamada.

Y eso es lo que tengo ya listo y andando. Pero hay algo más que puede ser útil. Siempre que compilo y salen errores, automáticamente presiono Ctrl+<. Este atajo me permite ir iterando por los errores; me lleva a cada linea que marca el compilador como si le hiciera doble click al error en el árbol de resultados. Pero ocurre que cuando en un mismo archivo hay varios errores, si al corregir el primero agrego o quito lineas de código, luego los demás se marcan en posiciones incorrectas porque dichas posiciones (números de linea) han quedado desactualizadas con esa edición. Ahora puedo agarrarme de las marcas en el margen para seguir esos cambios y saber dónde va a parar exactamente cada error, sin importar las ediciones que haga.

Y así, ahora que reescribí un poco el manejo de errores y me es más fácil agregarle cosas, iré pensando qué más puedo hacer para aprovechar mejor toda esta información en las próximas versiones. Como siempre, pueden dejar sus sugerencias en los comentarios.

No hay comentarios:

Publicar un comentario en la entrada