Non posso dire esattamente quali algoritmi vengono utilizzati da una particolare implementazione, ma posso fare alcune ipotesi plausibili. Un trie è una struttura dati molto utile per questo problema: l'IDE può mantenere un grande trie in memoria di tutti i simboli nel tuo progetto, con alcuni metadati extra in ogni nodo.
Quando digiti un carattere, questo segue un percorso nel trie. Tutti i discendenti di un particolare nodo trie sono possibili completamenti. L'IDE ha quindi solo bisogno di filtrare quelli fuori da quelli che hanno senso nel contesto corrente, ma ha solo bisogno di calcolarne quanti possono essere visualizzati nella finestra pop-up di completamento con tabulazione.
Il completamento con tabulazione più avanzato richiede un trie più complicato. Ad esempio, Visual Assist X ha una funzione per cui devi solo digitare le lettere maiuscole dei simboli CamelCase - ad esempio, se digiti SFN, ti mostra il simbolo SomeFunctionName
nella sua finestra di completamento con tabulazioni.
Il calcolo del trie (o di altre strutture dati) richiede l'analisi di tutto il codice per ottenere un elenco di tutti i simboli nel progetto. Visual Studio lo archivia nel proprio database IntelliSense, un .ncb
file archiviato insieme al progetto, in modo che non debba analizzare tutto ogni volta che si chiude e si riapre il progetto. La prima volta che apri un progetto di grandi dimensioni (ad esempio, uno che hai appena sincronizzato con il controllo del codice sorgente del modulo), VS impiegherà del tempo per analizzare tutto e generare il database.
Non so come gestisce i cambiamenti incrementali. Come hai detto, quando scrivi codice, la sintassi non è valida il 90% delle volte, e ripassare tutto ogni volta che sei inattivo comporterebbe un'enorme tassa sulla tua CPU con un vantaggio minimo, specialmente se stai modificando un file di intestazione incluso da un gran numero di file sorgente.
Ho il sospetto che (a) ripara solo ogni volta che costruisci effettivamente il tuo progetto (o forse quando lo chiudi / lo apri), o (b) esegue una sorta di analisi locale in cui analizza solo il codice dove hai appena modificato in modo limitato, solo per ottenere i nomi dei simboli pertinenti. Dal momento che il C ++ ha una grammatica così straordinariamente complicata, potrebbe comportarsi in modo strano negli angoli bui se stai usando una metaprogrammazione di modelli pesanti e simili.