c# - obtener - ¿Cómo puedo hacer que mi acción de nodo de sintaxis de diagnóstico de código funcione en archivos cerrados?
obtener valor de un atributo xml c# (1)
Estoy creando un conjunto de diagnósticos de código usando Roslyn (en la Vista previa de VS2015). Idealmente, me gustaría que los errores que producen actúen como errores persistentes, como si estuviera violando una regla de lenguaje normal.
Hay un montón de opciones, pero estoy teniendo dificultades para que cualquiera de ellas funcione de manera consistente. He logrado implementar una acción de nodo de sintaxis rudimentaria, es decir, una registrada con
context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, SyntaxKind.InvocationExpression);
en el método
Initialize
de mi clase de diagnóstico.
He aquí que cuando abro un archivo que viola este diagnóstico (mientras ejecuto el proyecto VSIX), VS2015 muestra un error:
- Squiggle rojo debajo del código correcto
- Bloque rojo en el margen
- Error en la lista de errores
Sin embargo, el error desaparece cuando cierro el archivo.
Intenté usar
context.RegisterCompilationEndAction
también, pero esto tiene dos problemas:
- Parece disparar inconsistentemente. Por lo general, cuando abro la solución, se dispara, pero no siempre. No se dispara en una limpieza / reconstrucción, lo que parece extraño.
-
Aunque los diagnósticos creados directamente en el método de análisis se disparan, para implementar los diagnósticos estoy usando un visitante, como este, que puede ser inepto:
private static void AnalyzeEndCompilation(CompilationEndAnalysisContext context) { foreach (var tree in context.Compilation.SyntaxTrees) { var visitor = new ReportingVisitor(context.Compilation.GetSemanticModel(tree)); visitor.Visit(tree.GetRoot()); foreach (var diagnostic in visitor.Diagnostics) { context.ReportDiagnostic(diagnostic); } } }
Sé que se están creando los diagnósticos (varias veces se
ReportDiagnostic
un punto de interrupción en la líneaReportDiagnostic
, pero no veo nada en la lista de errores. (Mientras que seReportDiagnostic
llamada deReportDiagnostic
similar al inicio del método, o una por árbol de sintaxis con la ruta del archivo).
¿Qué estoy haciendo mal aquí? El primer enfoque (una acción de nodo de sintaxis) sería ideal si fuera posible: me da exactamente el contexto que necesito. ¿Hay alguna configuración en las propiedades del proyecto que necesito para que el compilador la use para la compilación del "proyecto completo", así como solo para el manejo interactivo "en el IDE"? ¿Es esto quizás solo un poco de integración de Roslyn que aún no está terminada?
(Puedo incluir el código completo de la clase si fuera útil; en este caso, sospecho que sería más ruido que señal).
Para los problemas de archivos cerrados, nuestra intención es que todos los diagnósticos sean reportados, ya sea de archivos abiertos o cerrados. Hay una opción de usuario para ello en la vista previa en Herramientas / Opciones / Editor de texto / C # / Avanzado que puede alternar para incluir diagnósticos en archivos cerrados. Esperamos que esto sea el predeterminado antes de que se lance VS 2015. Sin embargo, tenga en cuenta que la opción solo se aplica al análisis dentro de VS. Si su analizador se pasa al compilador (agregando un analizador en el Explorador de soluciones o agregando una referencia de paquete NuGet a un paquete con un analizador, en lugar de instalar un VSIX en Visual Studio), el compilador informará todos los diagnósticos cuando compilaciones de usuarios, independientemente de si los archivos están abiertos o no.
Para el segundo problema con
RegisterCompilationEndedAnalyzer
, no se llama de manera confiable dentro de Visual Studio en la Vista previa de VS 2015.
Esto se debe a que hacemos algunas optimizaciones para evitar volver a analizar todo en busca de cambios "locales" dentro de los cuerpos de los métodos.
Por razones similares, actualmente no informamos los errores que se informan con ubicaciones
en los
cuerpos de los métodos.
Recientemente lo hemos cambiado para que VS inicie un nuevo análisis completo después de un retraso más prolongado, por lo que
RegisterCompilationEndedAnalyzer
debería llamarse de manera confiable en futuras compilaciones, e informaremos errores independientemente de la ubicación.
Sin embargo, para su caso, lo correcto es quedarse con un SyntaxNodeAnalyzer, cambiar la opción VS para habilitar el diagnóstico en archivos cerrados y adjuntar su diagnóstico a las opciones de compilación del proyecto.
¡Espero que esto ayude!