web-dev-qa-db-fra.com

Une nouvelle et complète implémentation d'Intellisense générique

Je suis intéressé à écrire un éditeur générique compatible Intellisense pour SQL et C # (et al. Si possible!). Je voudrais le faire en C # en tant que contrôle de type WPF richTextBox substitué ou étendu. Je sais qu'il existe de nombreux exemples de projets disponibles et j'ai implémenté une version de base de ma propre; mais la plupart des exemples que j'ai rencontrés (et même les miens) ne sont que cela, basiques .

Voici quelques exemples de code:

  1. DIY Intellisense par yetanotherchris

  2. CodeTextBox - un autre contrôle RichTextBox avec coloration syntaxique et Intellisense par Tamas Honfi

J'ai cependant trouvé un excellent exemple d'un éditeur SQL avec Intellisense QueryCommander SQL Editor By Mikael Håkansson qui semble bien fonctionner. Microsoft doit utiliser une bibliothèque XML de mots-clés de commande, mais ma question est: comment (en détail) Microsoft implémente-t-il son Intellisense (tel que vous tapez) et à quel point serait-il difficile pour moi de créer le mien avec le même standard?


Edit A: Un an plus tard, j'ai réussi à développer mon propre contrôle d'éditeur avec intellisense de base principalement pour mon "plaisir". Je pensais que je reviendrais fournir une liste de projets .NET disponibles gratuitement qui m'ont aidé avec mon propre développement et peuvent être utilisés immédiatement et gratuitement:

  1. ICSharpCode (WinForms)

  2. AvalonEdit (WPF)

  3. ScintillaNET (WinForms)

  4. Query Commander [par exemple d'implémentation d'intellisense] (WinForms)


Edit B: 15 mois après la question, je suis toujours à la recherche de nouveaux éditeurs améliorés. Celui-ci est sympa ...

  1. RoslynPAD est cool!

Edit C: 2 ans + après la question, j'ai trouvé les projets suivants, à la fois en utilisant WPF et soutenu par AvalonEdit.

  1. CodeCompletion pour AvalonEdit utilisant NRefactory. Ce projet est vraiment sympa et a une implémentation complète d'intellisense en utilisant NRefactory.

  2. ScriptCS ScriptCS facilite l'écriture et l'exécution de C # avec un simple éditeur de texte.

61
MoonKnight

Comment (en détail) Microsoft met-il en œuvre son Intellisense au fur et à mesure?

Je peut le décrire à n'importe quel niveau de détail que vous souhaitez nommer, mais je n'ai pas le temps pour plus qu'une brève explication. Je vais vous expliquer comment nous procédons à Roslyn.

Tout d'abord, nous construisons un modèle immuable du flux de jetons en utilisant une structure de données qui peut représenter efficacement modifications, car les modifications sont évidemment ce dont il va y avoir beaucoup.

L'idée clé pour la rendre efficace pour une réutilisation persistante est de représenter les longueurs de caractères des jetons mais pas leurs positions des caractères dans le tampon d'édition; rappelez-vous, un jeton à la fin du fichier va changer de position à chaque édition mais la longueur du jeton ne change pas. Vous devez à tout prix minimiser le nombre de re-lexings totaux si vous voulez être efficace sur des fichiers extrêmement volumineux.

Une fois que vous avez un modèle immuable qui peut gérer les insertions et les suppressions pour créer un flux de jeton immuable sans relexer le fichier entier à chaque fois, vous devez alors faire la chose même, mais pour la grammaire une analyse. C'est en pratique un problème beaucoup plus difficile. Je vous recommande d'obtenir un diplôme de premier cycle ou d'études supérieures en informatique avec un accent sur la théorie de l'analyseur si vous ne l'avez pas déjà fait. Nous avons obtenu l'aide de personnes titulaires d'un doctorat qui ont fait leur thèse sur la théorie de l'analyseur pour concevoir cette partie particulière de l'algorithme.

Ensuite, évidemment, construisez un analyseur grammatical qui peut analyser C #. Rappelez-vous, il doit analyser cassé C #, pas correct C #; IntelliSense doit fonctionner pendant que le programme est dans un état de non-compilation. Commencez donc par proposer des modifications à la grammaire qui ont de bonnes caractéristiques de récupération d'erreur.

OK, alors maintenant vous avez un analyseur qui peut efficacement effectuer une analyse grammaticale sans relexer ou réanalyser autre chose que la région éditée, la plupart du temps, ce qui signifie que vous pouvez faire le travail entre les frappes. J'ai oublié de mentionner, bien sûr, vous devrez trouver un mécanisme pour ne pas bloquer le thread d'interface utilisateur tout en faisant toutes ces analyses si l'analyse devait prendre plus de temps que le temps entre deux frappes . La nouvelle fonctionnalité "async/attente" de C # 5 devrait aider à cela. (Je peux vous dire par expérience personnelle: soyez prudent avec la prolifération des tâches et des jetons d'annulation. Si vous êtes imprudent, il est possible de se retrouver dans un état où il y a des dizaines de milliers de tâches annulées en attente, à savoir pas rapide.)

Maintenant que vous avez une analyse grammaticale, vous devez construire un analyseur sémantique. Comme vous ne faites qu'IntelliSense, il n'est pas nécessaire que ce soit un analyseur sémantique particulièrement sophistiqué. (Notre analyseur sémantique doit faire une analyse appropriée pour générer du code à partir de programmes corrects et une analyse d'erreur correcte à partir de programmes incorrects.) Mais bien sûr, encore une fois, il doit faire une bonne analyse sémantique sur les programmes cassés, ce qui augmente considérablement la complexité.

Mon conseil est de commencer par construire un analyseur sémantique de "haut niveau", en utilisant à nouveau un modèle immuable qui peut conserver l'état des types de code déclaré en source d'une édition à une autre. L'analyseur de niveau supérieur traite tout ce qui est pas une instruction ou une expression: déclarations de type, directives, espaces de noms, déclarations de méthode, constructeurs, destructeurs, etc. Les éléments qui composent la "forme" du programme lorsque le compilateur génère des métadonnées.

Métadonnées! J'ai oublié les métadonnées. Vous aurez besoin d'un lecteur de métadonnées. Vous devez être en mesure de produire IntelliSense sur des expressions qui se réfèrent aux types dans les bibliothèques, évidemment. Je recommande d'utiliser les bibliothèques CCI comme lecteur de métadonnées et non Reflection. Comme vous ne faites qu'IntelliSense, vous n'avez évidemment pas besoin d'un rédacteur de métadonnées.

Quoi qu'il en soit, une fois que vous disposez d'un analyseur sémantique de niveau supérieur, vous pouvez écrire un analyseur sémantique d'instructions et d'expressions qui analyse les types d'expressions dans une instruction donnée. Portez une attention particulière aux algorithmes recherche de nom et résolution de surcharge. L'inférence de type de méthode sera particulièrement délicate, en particulier dans les requêtes LINQ.

Une fois que vous avez tout cela, un moteur IntelliSense devrait être facile; déterminez simplement le type de l'expression à la position actuelle du curseur et affichez une liste déroulante de manière appropriée.

à quel point serait-il difficile pour moi de créer le mien de la même norme?

Eh bien, nous avons une équipe de, appelez-la dix personnes, et cela prendra probablement, appelez-le cinq ans tous ensemble pour que tout se fasse du début à la fin. Mais nous avons bien plus à faire que le moteur IntelliSense. C'est peut-être seulement 40% du travail. Oh, et la moitié de ces gens travaillent sur VB, maintenant que j'y pense. Mais ces gens ont en moyenne probablement cinq ou dix ans d'expérience dans ce genre de travail, ils sont donc plus rapides que vous si vous ne l'avez jamais fait auparavant.

Supposons donc que cela vous prenne environ dix à vingt ans de travail à temps plein, en travaillant seul, pour créer un moteur IntelliSense de qualité Roslyn pour C # qui puisse effectuer une analyse acceptable de près à correcte de grands programmes dans l'intervalle entre les frappes.

Plus longtemps si vous devez d'abord faire ce doctorat, évidemment.

Ou, vous pouvez simplement utiliser Roslyn, puisque c'est à cela que sert . Cela vous prendra probablement quelques heures, mais vous ne vous amusez pas à le faire vous-même. Et c'est amusant!

Vous pouvez télécharger la version préliminaire ici:

http://www.Microsoft.com/download/en/details.aspx?id=27746

122
Eric Lippert

C'est un domaine où Microsoft produit généralement d'excellents résultats - les outils de développement Microsoft sont vraiment géniaux. Et il y a un avantage commercial évident pour les ventes de leurs outils de développement et pour les ventes de Windows d'avoir le meilleur intellectuel, il est donc logique que Microsoft consacre le type de ressources qu'Eric décrit dans sa réponse merveilleusement détaillée. Pourtant, je pense qu'il vaut la peine de souligner quelques points:

  1. Vos clients peuvent ne pas avoir réellement besoin de toutes les fonctionnalités fournies par l'implémentation de Microsoft. La solution Microsoft peut être incroyablement sur-conçue en termes de fonctionnalités que vous devez fournir à vos clients/utilisateurs. À moins que vous n'implémentiez réellement un environnement de codage générique destiné à être compétitif avec Visual Studio, il est probable que certains aspects de votre utilisation prévue simplifient le problème ou vous permettent de faire des compromis sur la solution que Microsoft ressent. ils ne peuvent pas faire. Microsoft dépensera probablement des ressources pour réduire les temps de réponse qui sont déjà mesurés en centaines de millisecondes. Ce n'est peut-être pas quelque chose que vous devez faire. Microsoft consacre du temps à fournir une API à d'autres utilisateurs pour l'analyse de code. Cela ne fait probablement pas partie de votre plan. Hiérarchisez vos fonctionnalités et décidez de ce à quoi "assez bien" ressemble pour vous et vos clients, puis estimez le coût de la mise en œuvre.

  2. En plus de supporter les coûts évidents d'implémentation des exigences que vous n'avez peut-être pas réellement, Microsoft supporte également certains coûts qui peuvent ne pas être évidents si vous n'avez pas travaillé en équipe. Il y a d'énormes coûts de communication associés aux équipes. Il est en fait incroyablement facile d'avoir cinq personnes intelligentes plus longues à produire une solution qu'il n'en faut à une seule personne intelligente pour produire la solution équivalente. Certains aspects des pratiques d'embauche et de la structure organisationnelle de Microsoft rendent ce scénario plus probable. Si vous embauchez un groupe de personnes intelligentes avec des ego et que vous les autorisez tous à prendre des décisions, vous pouvez également obtenir une solution 5% meilleure pour 500% du coût. Cette solution améliorée de 5% pourrait être rentable pour Microsoft, mais elle pourrait être mortelle pour une petite entreprise.

  3. Passer d'une solution 1 personne à une solution 5 personnes augmente les coûts, mais ce ne sont que les coûts de développement intra-équipe. Microsoft a séparé équipes qui se consacrent à (grossièrement) la conception, le développement et les tests, même pour une seule fonctionnalité. La communication liée au projet entre pairs à travers ces frontières a une friction plus élevée que dans chacune des disciplines. Cela augmente non seulement les coûts de communication entre les individus, mais cela se traduit également par des équipes de plus grande taille. Et plus que cela - puisque ce n'est pas une seule équipe de 12 personnes, mais plutôt 3 équipes de 5 personnes, il y a 3 fois le coût de la communication. Plus de coûts que Microsoft a choisi de supporter, ce qui peut ne pas se traduire par des coûts similaires pour d'autres sociétés.

Mon propos ici n'est pas de décrire Microsoft comme une entreprise inefficace. Mon point est que Microsoft prend une tonne de décisions sur tout, depuis l'embauche, l'organisation de l'équipe, la conception et la mise en œuvre qui partent d'hypothèses sur la rentabilité et les risques qui ne s'appliquent tout simplement pas aux entreprises qui ne sont pas Microsoft.

En ce qui concerne l'intellisense, il existe différentes façons de penser le problème. Microsoft produit une solution très générique et réutilisable qui ne résout pas seulement l'intellisense, mais cible également la navigation dans le code, la refactorisation et diverses autres utilisations pour l'analyse de code. Vous n'avez pas besoin de faire les choses de la même manière si votre seul objectif est de faciliter la saisie de code pour les développeurs sans avoir à taper beaucoup. Cibler cette fonctionnalité ne prend pas des années d'efforts et il y a toutes sortes de choses créatives que vous pouvez faire si vous ne fournissez pas seulement une API, mais vous contrôlez également l'interface utilisateur.

16
Ajs