No puedo decir exactamente qué algoritmos se utilizan en una implementación en particular, pero puedo hacer algunas conjeturas. Un trie es una estructura de datos muy útil para este problema: el IDE puede mantener un gran trie en la memoria de todos los símbolos de su proyecto, con algunos metadatos adicionales en cada nodo.
Cuando escribe un carácter, recorre un camino en el trie. Todos los descendientes de un nodo trie particular son posibles completaciones. Luego, el IDE solo necesita filtrarlos por aquellos que tengan sentido en el contexto actual, pero solo necesita calcular tantos como se puedan mostrar en la ventana emergente de finalización de pestañas.
La finalización de pestañas más avanzada requiere un proceso más complicado. Por ejemplo, Visual Assist X tiene una función mediante la cual solo necesita escribir las letras mayúsculas de los símbolos de CamelCase; por ejemplo, si escribe SFN, le muestra el símbolo SomeFunctionName
en su ventana de finalización de tabulación.
Calcular el trie (u otras estructuras de datos) requiere analizar todo su código para obtener una lista de todos los símbolos en su proyecto. Visual Studio almacena esto en su base de datos IntelliSense, un .ncb
archivo almacenado junto con su proyecto, para que no tenga que analizar todo cada vez que cierra y vuelve a abrir su proyecto. La primera vez que abre un proyecto grande (digamos, uno que acaba de sincronizar el control de fuente del formulario), VS se tomará el tiempo para analizar todo y generar la base de datos.
No sé cómo maneja los cambios incrementales. Como dijiste, cuando escribes código, la sintaxis es inválida el 90% del tiempo, y analizar todo cada vez que estás inactivo supondría un gran impuesto sobre tu CPU por muy poco beneficio, especialmente si estás modificando un archivo de encabezado incluido por una gran cantidad de archivos fuente.
Sospecho que (a) solo repara cada vez que realmente construye su proyecto (o posiblemente cuando lo cierra / abre), o (b) realiza algún tipo de análisis local donde solo analiza el código donde acaba de editado de forma limitada, solo para obtener los nombres de los símbolos relevantes. Dado que C ++ tiene una gramática tan extraordinariamente complicada, puede comportarse de manera extraña en los rincones oscuros si está utilizando metaprogramación de plantilla pesada y similares.