{"id":240595,"date":"2022-12-01T08:00:33","date_gmt":"2022-12-01T16:00:33","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/visualstudio\/?p=240595"},"modified":"2022-11-30T09:43:49","modified_gmt":"2022-11-30T17:43:49","slug":"building-a-new-javascript-linting-experience-in-visual-studio","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/visualstudio\/building-a-new-javascript-linting-experience-in-visual-studio\/","title":{"rendered":"Building a new JavaScript linting experience in Visual Studio"},"content":{"rendered":"<p style=\"text-align: justify;\"><span data-contrast=\"auto\">Available today in the 17.4 public release, Visual Studio has revamped its ESLint support! The new linting experience includes:<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<ul>\n<li data-leveltext=\"-\" data-font=\"Calibri\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559684&quot;:-2,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Calibri&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;-&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" aria-setsize=\"-1\" data-aria-posinset=\"1\" data-aria-level=\"1\"><span data-contrast=\"auto\">Linting support \u2013 for not only JavaScript and TypeScript files, but also for JSX\/TSX, Vue and HTML files.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/li>\n<li data-leveltext=\"-\" data-font=\"Calibri\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559684&quot;:-2,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Calibri&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;-&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" aria-setsize=\"-1\" data-aria-posinset=\"2\" data-aria-level=\"1\"><a href=\"https:\/\/learn.microsoft.com\/en-us\/visualstudio\/ide\/quick-actions?view=vs-2022\"><span data-contrast=\"none\">Quick actions and fixes<\/span><\/a><span data-contrast=\"none\">,<\/span><span data-contrast=\"auto\"> which allow you to\u00a0<a href=\"https:\/\/eslint.org\/docs\/latest\/developer-guide\/working-with-rules#applying-fixes\">auto-fix errors<\/a> or disable ESLint rules on a single line or an entire file.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/li>\n<li data-leveltext=\"-\" data-font=\"Calibri\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559684&quot;:-2,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Calibri&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;-&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" aria-setsize=\"-1\" data-aria-posinset=\"3\" data-aria-level=\"1\"><span data-contrast=\"auto\">Flexible global defaults under <em>Tools -&gt; Options -&gt; Text Editor -&gt; JavaScript\/TypeScript -&gt; Linting<\/em> that are overridable with project configuration.<\/span><\/li>\n<li data-leveltext=\"-\" data-font=\"Calibri\" data-listid=\"2\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559684&quot;:-2,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Calibri&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;-&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" aria-setsize=\"-1\" data-aria-posinset=\"4\" data-aria-level=\"1\"><span data-contrast=\"auto\">A guiding installation wizard that will help you set up your ESLint configuration and dependencies based on your project.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/li>\n<\/ul>\n<p><span data-contrast=\"auto\">But the main purpose of this post is not to list all of the cool things that the new linting service provides, but to tell you a little bit about the story behind it. I joined Microsoft at the beginning of 2022, and as an eager software engineer on the fantastic TypeScript tooling team, I was curious about what my first large project might be.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"auto\">It all started when adding support for the latest version of ESLint, the popular JavaScript linter. ESLint 8 had a few breaking change<\/span><span data-contrast=\"auto\">s<\/span><span data-contrast=\"auto\"> in its linter interface<\/span><span data-contrast=\"auto\">,<\/span><span data-contrast=\"auto\"> and that required an update in Visual Studio\u2019s integration. While working on the fix, I realized that our implementation had not been updated in a while and was missing several features that other IDEs offered. This was the opportunity I was looking for: We would bring out the full power of ESLint in Visual Studio, creating a new linting experience for our users! As a beginner C# developer that had never ventured into Visual Studio\u2019s extensibility APIs (I would often scratch my head wondering what MEF was), I had no idea of where to begin. However, from my web development past, I knew how important those squiggles were and how much they impact the programming experience when writing JavaScript code, and so I ignored my fears and thrived to deliver the squiggles I would like to have myself.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h4>An LSP extension inspired from vscode-eslint<\/h4>\n<p><span data-contrast=\"auto\">The goal was for the linting experience in Visual Studio to be on par with the one in VS Code. The editor&#8217;s support for disabling ESLint rules, auto fixing errors, and the settings available for tuning the linter\u2019s behavior are highly beloved features by VS Code users.<\/span><\/p>\n<p><span data-contrast=\"auto\">Fortunately, there was a linting server providing this functionality, and a protocol on how to communicate with it. The extension powering VS Code\u2019s ESLint support is <\/span><a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=dbaeumer.vscode-eslint\"><span data-contrast=\"none\">vscode-eslint<\/span><\/a><span data-contrast=\"auto\">, which is often featured as one of the most beloved extensions for JavaScript and TypeScript development. vscode-eslint is an <\/span><a href=\"https:\/\/microsoft.github.io\/language-server-protocol\/overviews\/lsp\/overview\/\"><span data-contrast=\"none\">LSP<\/span><\/a><span data-contrast=\"auto\"> (Language Service Protocol) extension, with a server handling linting requests and a client that communicates with the editing tool to display the server results. For example, if the user opens a <\/span><span data-contrast=\"auto\">JavaScript file, the LSP client will notify the server that a document of interest has been opened, the server will compute the linting errors and send them back to the client, and then the client will provide the core editor with diagnostics to display in the document and error list. Thanks to the standardized communication defined by the language server protocol, a single server can be re-used in multiple development tools, and tools can support new extensions with minimal effort.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"auto\">The LSP-based architecture of vscode-eslint meant that our goal was feasible: Visual Studio\u2019s linting integration could be of the same quality as VS Code\u2019s, since they could use the same server behind the scenes. We still had to write the Visual Studio client, which would make those linting squiggles show up in the editor.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"auto\">I don\u2019t want to bore you with all the technical details (mostly because they involve me debugging JSON error responses), but I do want to mention some of the things we learned from this experience:<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<ul>\n<li data-leveltext=\"-\" data-font=\"Calibri\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559684&quot;:-2,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Calibri&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;-&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" aria-setsize=\"-1\" data-aria-posinset=\"1\" data-aria-level=\"1\"><span data-contrast=\"auto\">Extensions should feel natural to its host. The VS Code extension relies on workspace configurations for storing local linting settings, but most Visual Studio developers use projects and solutions to organize their code. We then decided to use project properties for these local settings, respecting the IDE\u2019s essence.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/li>\n<li data-leveltext=\"-\" data-font=\"Calibri\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559684&quot;:-2,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Calibri&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;-&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" aria-setsize=\"-1\" data-aria-posinset=\"2\" data-aria-level=\"1\"><span data-contrast=\"auto\">Documentation is key. From the LSP specification listing the relevant requests that our client had to handle, to the fantastic extensions from our dear <\/span><a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/author\/madsk\/\"><span data-contrast=\"none\">Mads<\/span><\/a><span data-contrast=\"auto\"> that illustrate how to use several of Visual Studio\u2019s extensibility services. Implementing this feature motivated me to also give back to the extensibility community, and now I try to improve existing documentation (or add new one) that captures the things I learn.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/li>\n<li data-leveltext=\"-\" data-font=\"Calibri\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559684&quot;:-2,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Calibri&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;-&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" aria-setsize=\"-1\" data-aria-posinset=\"3\" data-aria-level=\"1\"><span data-contrast=\"auto\">LSP extensibility is amazing. It might be a bit of a learning curve to get started, but it abstracts the specifics of the editor\u2019s implementation (no need to implement a custom ITagger to provide error squiggles!), allowing you to build a reusable and more compact extension.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h4>Using the new linting service<\/h4>\n<p><span data-contrast=\"auto\">To get started with ESLint in your project, you\u2019ll first need to install the <\/span><a href=\"https:\/\/www.npmjs.com\/package\/eslint\"><span data-contrast=\"none\">npm module<\/span><\/a><span data-contrast=\"auto\"> by running <code>npm install \u2013dev eslint<\/code> in the command line. You might need to install additional linting plugins; for example, you may need <\/span><a href=\"https:\/\/typescript-eslint.io\/\"><span data-contrast=\"none\">TypeScript ESLint<\/span><\/a><span data-contrast=\"auto\">, which enables ESLint to run on TypeScript code and includes rules that are specific to the extra type information.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><!--more--><\/p>\n<p><span data-contrast=\"auto\">Once you have the necessary dependencies installed, enable ESLint in <em>Tools &gt; Options &gt; Text Editor &gt; JavaScript\/TypeScript &gt; Linting<\/em>, and include an <code>.eslintrc<\/code> file to customize your linting configuration. The ESLint website has <\/span><a href=\"https:\/\/eslint.org\/docs\/latest\/user-guide\/configuring\/\"><span data-contrast=\"none\">great documentation<\/span><\/a><span data-contrast=\"auto\"> about how to use this file.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"auto\">And that\u2019s it! You should now be able to see error squiggles when your code doesn\u2019t follow your linting rules:<\/span><\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2022\/11\/Picture1.png\"><img decoding=\"async\" class=\"wp-image-240598 size-full aligncenter\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2022\/11\/Picture1.png\" alt=\"Linting error diagnostic\" width=\"734\" height=\"267\" srcset=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2022\/11\/Picture1.png 734w, https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2022\/11\/Picture1-300x109.png 300w\" sizes=\"(max-width: 734px) 100vw, 734px\" \/><\/a><\/p>\n<p><span class=\"TextRun SCXW243581981 BCX8\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun CommentStart SCXW243581981 BCX8\">By right-clicking on the squiggle<\/span><span class=\"NormalTextRun SCXW243581981 BCX8\"> and viewing the available quick actions<\/span><span class=\"NormalTextRun CommentStart SCXW243581981 BCX8\">, you\u2019ll be able to <\/span><span class=\"NormalTextRun SCXW243581981 BCX8\">disabl<\/span><span class=\"NormalTextRun SCXW243581981 BCX8\">e<\/span><span class=\"NormalTextRun SCXW243581981 BCX8\"> the error or <\/span><span class=\"NormalTextRun SCXW243581981 BCX8\">fix<\/span><span class=\"NormalTextRun SCXW243581981 BCX8\"> it!<\/span><\/span><span class=\"EOP SCXW243581981 BCX8\" data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2022\/11\/Picture2.png\"><img decoding=\"async\" class=\"wp-image-240597 size-full aligncenter\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2022\/11\/Picture2.png\" alt=\"Linting error squiggle\" width=\"552\" height=\"234\" srcset=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2022\/11\/Picture2.png 552w, https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2022\/11\/Picture2-300x127.png 300w\" sizes=\"(max-width: 552px) 100vw, 552px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<h4>Next steps<\/h4>\n<p><span data-contrast=\"auto\">You can try out the new linting experience in Visual Studio 17.4 (note that linting in Vue and HTML will be available in the next release). Make sure to review the <\/span><a href=\"https:\/\/learn.microsoft.com\/en-us\/visualstudio\/javascript\/linting-javascript?view=vs-2022\"><span data-contrast=\"none\">documentation<\/span><\/a><span data-contrast=\"auto\"> for detailed instructions on the required setup, and please submit a <\/span><a href=\"https:\/\/developercommunity.visualstudio.com\/VisualStudio\"><span data-contrast=\"none\">feedback ticket<\/span><\/a><span data-contrast=\"auto\"> if you encounter any issues or have an idea of what other linting enhancements you would like to see in Visual Studio.<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"auto\">Enjoy your squiggles!<\/span><span data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Available today in the 17.4 public release, Visual Studio has revamped its ESLint support! The new linting experience includes:\u00a0 Linting support \u2013 for not only JavaScript and TypeScript files, but also for JSX\/TSX, Vue and HTML files.\u00a0 Quick actions and fixes, which allow you to\u00a0auto-fix errors or disable ESLint rules on a single line or [&hellip;]<\/p>\n","protected":false},"author":102544,"featured_media":255385,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1388,155,1029],"tags":[124,125,6815,1408],"class_list":["post-240595","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-extensibility","category-visual-studio","category-web","tag-javascript","tag-typescript","tag-visual-studio-2022","tag-web"],"acf":[],"blog_post_summary":"<p>Available today in the 17.4 public release, Visual Studio has revamped its ESLint support! The new linting experience includes:\u00a0 Linting support \u2013 for not only JavaScript and TypeScript files, but also for JSX\/TSX, Vue and HTML files.\u00a0 Quick actions and fixes, which allow you to\u00a0auto-fix errors or disable ESLint rules on a single line or [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/posts\/240595","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/users\/102544"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/comments?post=240595"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/posts\/240595\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/media\/255385"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/media?parent=240595"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/categories?post=240595"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/tags?post=240595"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}