Una Nueva y completa Implementación de Intellisense Genérico


Estoy interesado en escribir un editor genérico habilitado para Intellisense para SQL y C# (et al. si es posible!). Me gustaría hacer esto en C# como un control de tipo WPF RichTextBox anulado o extendido. Sé que hay muchos proyectos de ejemplo disponibles y he implementado una versión basic propia; pero la mayoría de los ejemplos que he encontrado (y de hecho el mío) son solo eso, basic.

Un par de ejemplos de código son:

  1. BRICOLAJE Intellisense De yetanotherchris

  2. CodeTextBox - otro control RichTextBox con resaltado de sintaxis e Intellisense Por Tamas Honfi

Sin embargo, he encontrado un gran ejemplo de un editor SQL con Intellisense QueryCommander SQL Editor De Mikael Håkansson que parece funcionar bien. Microsoft debe usar una biblioteca XML de palabras clave de comando, pero mi pregunta es: ¿Cómo (en detalle) Microsoft implementa su Intellisense (a medida que escribe Intellisense) y ¿qué tan difícil sería para mí crear el mío propio del mismo estándar?


Editar A: Un año después y he logrado desarrollar mi propio control de editor con intellisense básico principalmente para mi propio "disfrute". Pensé que volvería a proporcionar una lista de proyectos. NET disponibles gratuitamente que me ayudaron con mi propio desarrollo y se pueden usar fuera de la caja y de forma gratuita:

  1. ICSharpCode (WinForms)

  2. AvalonEdit (WPF)

  3. ScintillaNET (WinForms)

  4. Query Commander [por ejemplo de implementación de intellisense] (WinForms)


Edición B: 15 meses después de la pregunta todavía estoy buscando nuevos editores mejorados. Este es bonito...

  1. RoslynPAD es genial!

Editar C: 2 años + a partir de la pregunta, he encontrado los siguientes proyectos, ambos usando WPF y respaldados por AvalonEdit.

  1. CodeCompletion para AvalonEdit usando NRefactory. Este proyecto es realmente agradable y tiene una implementación completa de intellisense utilizando NRefactory.

  2. ScriptCS ScriptCS facilita la escritura y ejecución de C# con un simple editor de texto.

Author: MoonKnight, 2012-03-04

2 answers

¿Cómo (en detalle) Microsoft implementa su Intellisense mientras escribe?

Puedo describirlo a cualquier nivel de detalle que quiera nombrar, pero no tengo tiempo para más que una breve explicación. Te explicaré cómo lo hacemos en Roslyn.

Primero, construimos un modelo inmutable del flujo de tokens utilizando una estructura de datos que puede representar eficientemente ediciones, ya que obviamente las ediciones son precisamente lo que va a haber mucho.

El la información clave para hacer que sea eficiente para la reutilización persistente es representar las longitudes de caracteres de los tokens, pero no sus posiciones de caracteres en el búfer de edición; recuerde, un token al final del archivo va a cambiar de posición en cada edición, pero la longitud del token no cambia. Debe minimizar a toda costa el número total de re-lexings si desea ser eficiente en archivos extremadamente grandes.

Una vez que tenga un modelo inmutable que pueda manejar inserciones y eliminaciones para construir un flujo de token inmutable sin volver a lexar todo el archivo cada vez, entonces tiene que hacer lo mismo , pero para el análisis gramatical. Esto es en la práctica un problema considerablemente más difícil. Te recomiendo que obtengas un título de pregrado o posgrado en ciencias de la computación con énfasis en la teoría del analizador si aún no lo has hecho. Obtuvimos la ayuda de personas con doctorado que hicieron sus tesis sobre la teoría del analizador para diseñar este poco en particular de algoritmo.

Entonces, obviamente, construya un analizador gramatical que pueda analizar C#. Recuerde, tiene que analizar rotoC#, no correcto C#; IntelliSense tiene que funcionar mientras el programa no está compilando. Así que comience por llegar a modificaciones a la gramática que tienen buenas características de recuperación de errores.

OK, así que ahora tienes un analizador que puede hacer análisis gramatical de manera eficiente sin volver a lexing o volver a analizar nada más que la región editada, la mayoría del tiempo, lo que significa que puede hacer el trabajo entre pulsaciones de teclado. Olvidé mencionar que, por supuesto, tendrá que llegar a algún mecanismo para no bloquear el subproceso de interfaz de usuario mientras realiza todos estos análisis si el análisis tarda más que el tiempo entre dos pulsaciones de teclas. La nueva característica" async/await " de C# 5 debería ayudar con eso. (Te lo puedo decir por experiencia personal: ten cuidado con la proliferación de tareas y tokens de cancelación. Si eres descuidado, es es posible llegar a un estado donde hay decenas de miles de tareas canceladas pendientes, y eso es no rápido.)

Ahora que tienes un análisis gramatical necesitas construir un analizador semántico. Dado que solo está haciendo IntelliSense, no necesita ser un analizador semántico particularmente sofisticado. (Nuestro analizador semántico debe hacer un análisis adecuado para generar código a partir de programas correctos y corregir el análisis de errores de programas incorrectos.) Pero por supuesto, una vez más, tiene que hacer un buen análisis semántico en programas rotos, lo que aumenta la complejidad considerablemente.

Mi consejo es comenzar por construir un analizador semántico de "nivel superior", nuevamente usando un modelo inmutable que pueda persistir el estado de los tipos declarados en el código fuente de edición a edición. El analizador de nivel superior se ocupa de todo lo que es no una declaración o expresión: declaraciones de tipos, directivas, espacios de nombres, declaraciones de métodos, constructores, destructores, etc. Las cosas que conforman la "forma" del programa cuando el compilador genera metadatos.

Metadatos! Me olvidé de los metadatos. Necesitarás un lector de metadatos. Es necesario ser capaz de producir IntelliSense en expresiones que se refieren a tipos en bibliotecas, obviamente. Recomiendo usar las bibliotecas CCI como lector de metadatos, y no como Reflejo. Dado que solo está haciendo IntelliSense, obviamente no necesita un escritor de metadatos.

De todos modos, una vez que tenga un analizador semántico de nivel superior, a continuación, puede escribir un analizador semántico de sentencias y expresiones que analice los tipos de expresiones en una sentencia dada. Preste especial atención a los algoritmos búsqueda de nombres y resolución de sobrecarga. La inferencia del tipo de método será particularmente complicada, especialmente dentro de consultas LINQ.

Una vez que tenga todo eso, un motor IntelliSense debería ser fácil; simplemente calcule el tipo de expresión en la posición actual del cursor y muestre un menú desplegable adecuadamente.

¿Qué tan difícil sería para mí crear el mío propio del mismo estándar?

Bueno, tenemos un equipo de, llámalo diez personas, y probablemente tomará, llámalo cinco años todos juntos para conseguir todo el asunto hecho de principio a fin. Pero tenemos mucho más que hacer que solo el motor IntelliSense. Eso es tal vez sólo el 40% del trabajo. Y la mitad de esa gente trabaja en VB, ahora que lo pienso. Pero esas personas tienen en promedio probablemente cinco o diez años experiencia en hacer este tipo de trabajo, por lo que son más rápidos en ello de lo que será si nunca has hecho esto antes.

Así que digamos que debería tomar alrededor de diez a veinte años de trabajo a tiempo completo, trabajando solo, para construir un motor IntelliSense de calidad Roslyn para C# que pueda hacer un análisis aceptablemente cercano a correcto de programas grandes en el tiempo entre pulsaciones de teclas.

Más si necesitas hacer ese doctorado primero, obviamente.

O, simplemente usar Roslyn, ya que es para qué sirve . Eso te llevará probablemente unas horas, pero no tienes la diversión de hacerlo tú mismo. Y es divertido!

Puede descargar la versión preliminar aquí:

Http://www.microsoft.com/download/en/details.aspx?id=27746

 119
Author: Eric Lippert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-04 16:42:43

Este es un área donde Microsoft normalmente produce grandes resultados - herramientas de desarrollo de Microsoft realmente son impresionantes. Y hay una clara ventaja comercial para las ventas de sus herramientas de desarrollo y para las ventas de Windows al tener el mejor intellisense, por lo que tiene sentido que Microsoft dedique el tipo de recursos que Eric describe en su respuesta maravillosamente detallada. Aún así, creo que vale la pena señalar algunas de las cosas:

  1. Sus clientes pueden no necesitar realmente todos los características que proporciona la implementación de Microsoft. La solución de Microsoft podría estar increíblemente sobre-diseñada en términos de las características que usted necesita proporcionar a sus clientes/usuarios. A menos que realmente esté implementando un entorno de codificación genérico que esté destinado a ser competitivo con Visual Studio, es probable que haya aspectos de su uso previsto que simplifiquen el problema o que le permitan hacer compromisos sobre la solución que Microsoft considera que no se puede hacer. Microsoft probablemente gastará recursos disminuyendo los tiempos de respuesta que ya se miden en cientos de milisegundos. Puede que no sea algo que tengas que hacer. Microsoft está dedicando tiempo a proporcionar una API para que otros la utilicen para el análisis de código. Eso probablemente no es parte de tu plan. Priorice sus características y decida qué aspecto tiene "lo suficientemente bueno" para usted y sus clientes, luego calcule el costo de implementarlo.

  2. Además de asumir los costos obvios de al implementar requisitos que en realidad no tiene, Microsoft también conlleva algunos costos que pueden no ser obvios si no ha trabajado en un equipo. Hay enormes costos de comunicación asociados con los equipos. En realidad, es increíblemente fácil que cinco personas inteligentes tarden más en producir una solución que una sola persona inteligente en producir la solución equivalente. Hay aspectos de las prácticas de contratación de Microsoft y la estructura organizativa que hacen que este escenario sea más probable. Si contrate a un grupo de personas inteligentes con egos y luego empodere a todos ellos para tomar decisiones, usted también puede obtener una solución 5% mejor por el 500% del costo. Esa solución 5% mejor podría ser rentable para Microsoft, pero podría ser mortal para una pequeña empresa.

  3. Pasar de una solución de 1 persona a una solución de 5 personas aumenta los costos, pero eso es solo los costos de desarrollo dentro del equipo. Microsoft tiene equipos separados que se dedican (aproximadamente) al diseño, desarrollo y pruebas incluso para una sola función. La comunicación relacionada con el proyecto entre pares a través de estos límites tiene mayor fricción que dentro de cada una de las disciplinas. Esto no solo aumenta los costos de comunicación entre las personas, sino que también resulta en un mayor tamaño de equipo. Y más que eso, ya que no es un solo equipo de 12 personas, sino que es 3 equipos de 5 personas, hay 3 veces el costo de comunicación al alza. Más costos que Microsoft ha elegido llevar que puede no traducirse a similares costes para otras empresas.

Mi punto aquí no es describir a Microsoft como una empresa ineficiente. Mi punto es que Microsoft toma un montón de decisiones sobre todo, desde la contratación, la organización del equipo, el diseño y la implementación que parten de suposiciones sobre la rentabilidad y el riesgo que simplemente no se aplican a las empresas que no son Microsoft.

En términos de la cosa intellisense, hay varias maneras de pensar sobre el problema. Microsoft está produciendo un solución muy genérica y reutilizable que no solo resuelve intellisense, sino que también se dirige a la navegación de código, la refactorización y varios otros usos para el análisis de código. No necesita hacer las cosas de la misma manera si su único objetivo es facilitar a los desarrolladores ingresar código sin tener que escribir mucho. Segmentar esa función no requiere años de esfuerzo y hay todo tipo de cosas creativas que puedes hacer si no solo proporcionas una API, sino que también controlas la interfaz de usuario.

 16
Author: Ajs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-04 20:00:30