Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Vscode+babel then develops a plug-in that intelligently removes unused variables

2025-03-30 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/01 Report--

This article is about vscode+babel and then develop an intelligent plug-in to remove unused variables. The editor thinks it is very practical, so I share it with you. I hope you can get something after reading this article. Let's take a look at it with the editor.

Vscode has become one of the indispensable front-end development tools. I think the reason why vscode is favored by developers has a lot to do with its "omnipotent" plug-in system. In our work, we can use it to develop pure tool-based plug-ins, and we can also use it to develop some functional plug-ins that combine with the company's business. Here I share a plug-in that can intelligently remove unused variables by combining with babel.

Text

Today, let's first familiarize ourselves with the process of building the vscode plug-in project.

1. Initialize a project using official scaffolding

Install scaffolding

# npm form npm install-g yo generator-code# yarn form yarn global add yo generator-code

Running scaffolding

# run scaffolding yo code

Choose the template, considering that some developers are not familiar with TypeScript, so we choose New Extension (JavaScript) here.

? What type of extension do you want to create? New Extension (JavaScript)? What's the name of your extension? Rm-unuse-var? What's the identifier of your extension? Rm-unuse-var? What's the description of your extension? Remove unused variables? Enable JavaScript type checking in 'jsconfig.json'? Yes? Initialize a git repository? Yes? Which package manager to use? Yarn

This is the directory structure we finally generated.

Let's try this plug-in first.

Clicking the run button above will open a new vscode window, press Ctrl+Shift+P and enter Hello World in the new window, and you will see a prompt box in the lower right corner of the window, indicating that our first vscode plug-in has run successfully.

2. Custom commands, shortcut keys, menus

Many functions of the vscode plug-in are based on individual commands. We can customize some commands, which will appear in the command list after pressing Ctrl+Shift+P. At the same time, you can configure shortcut keys for commands, configure explorer menus, editor menus, title menus, drop-down menus, upper-right icons, and so on.

3. How to add a command list

Package.json partial configuration

{/ / extended activation event "activationEvents": ["onCommand:rm-unuse-var.helloWorld"], / / entry file "main": ". / extension.js", / / add instruction "contributes": {"commands": [{/ / the value here must be the same as the value configured in activationEvents "command": "rm-unuse-var.helloWorld" / / this is the name of our instruction You can change the value here and re-run the plug-in to try "title": "Hello World"}]}}

Shortcut keys are the most convenient way to use them in development, so let's modify the configuration so that the plug-in supports keyboard shortcuts.

{"contributes": {"commands": [{/ / the value here must be the same as the value configured in activationEvents "command": "rm-unuse-var.helloWorld", / / this is the name of our instruction You can change the value here to re-run the plug-in "title": "Hello World"}], / / Shortcut key binding "keybindings": [{"command": "rm-unuse-var.helloWorld", "key": "ctrl+6", "mac": "cmd+6"}]}}

Let's rerun it and use the shortcut key Ctrl+6 to see if our plug-in works properly. Yes, it's that simple. Our plug-in can already run in the form of shortcut keys.

4. It's too corny to call helloWorld. Next, let's change the name of the instruction.

Package.json

{"activationEvents": ["onCommand:rm-unuse-var.rm-js-var"], "main": ". / extension.js", "contributes": {"commands": [{"command": "rm-unuse-var.rm-js-var", "title": "Hello World"}] "keybindings": [{"command": "rm-unuse-var.rm-js-var", "key": "ctrl+6", "mac": "cmd+6"}

Because we have registered the name of the instruction in extension.js, we also need to modify it synchronously.

Let disposable = vscode.commands.registerCommand ("rm-unuse-var.rm-js-var", function () {vscode.window.showInformationMessage ("Hello World from rm-unuse-var!");}); 5. Install babel related libraries

We can modify the code in three steps.

1. Parse the code into AST syntax tree 2, traverse the modified AST syntax tree 3, and generate new code according to the modified AST syntax tree

Babel has a corresponding library to deal with these three steps.

@ babel/parser generates AST syntax tree, document address (https://www.babeljs.cn/docs/babel-parser)

@ babel/traverse traverses the AST syntax tree, document address (https://www.babeljs.cn/docs/babel-traverse)

@ babel/generator generates code based on the AST syntax tree, document address (https://www.babeljs.cn/docs/babel-generator)

@ babel/types tool library, document address (https://www.babeljs.cn/docs/babel-types)

6. Let's take a look at the basic usage of these libraries, such as implementing a function that converts the arrow function of es6 into a normal function

Before conversion

Const say = () = > {console.log ("hello");}

After conversion

Function say () {console.log ("hello");}

The code is implemented, and the code is written for reference only.

Const t = require ("@ babel/types"); const parser = require ("@ babel/parser"); const traverse = require ("@ babel/traverse"). Default;const generate = require ("@ babel/generator") .default;// 1, parse the code into AST syntax tree const ast = parser.parse (`const say = () = > {console.log ("hello");}; `) / / 2. Traverse and modify the AST grammar tree traverse (ast, {VariableDeclaration (path) {const {node} = path; / / write to find the first declaration const declaration = node.declarations [0]; / / the defined content const init = declaration.init / / determine whether it is an arrow function if (t.isArrowFunction_Expression (init)) {/ / replace the original expression with the newly generated function path.replaceWith (t.functionDeclaration (declaration.id, init.params, init.body, init.generator, init.async);}},}) / / 3. Generate new code console.log (generate (ast) .code) based on the modified AST syntax tree; / * function say () {console.log ("hello");} * /

Many students must be curious that now our expression is relatively simple, if the definition of nesting will be very deep and complex, at this time how to know which node to replace? In fact, you can use astexplorer.net/ here, which is a website that converts AST online. We can open two windows, put the pre-conversion code in the first window, and put the interface to be converted in the second window. At this time, we can compare the differences before and after the conversion to implement our code.

6. Think about how to implement the plug-in?

1. Get the code of the js file currently open by the editor 2, parse the code into the AST syntax tree 3, traverse the AST syntax tree, delete the unused definition 4, generate new code based on the modified AST syntax tree 5, and replace the code of the current js file

We have already learned 2 and 4 of them, and then we just need to see how to implement 1, 3 and 5.

1 and 5 We can use the methods provided by vscode

1. Get the code of the js file currently opened by the editor

Import * as vscode from "vscode"; / / the currently opened file const {activeTextEditor} = vscode.window;// and then you can easily get our code through getText under document const code = activeTextEditor.document.getText ()

5. Replace the code of the current js file

ActiveTextEditor.edit ((editBuilder) = > {editBuilder.replace (/ / because we want full file replacement, we need to define an interval new vscode.Range (new vscode.Position (0,0), new vscode.Position (activeTextEditor.document.lineCount + 1,0)), / / our new code generate (ast). Code);})

All right, then we're down to step 3 of the core.

3. Traverse the AST syntax tree to delete unused definitions

Let's take a look at what unused definitions contain.

Import vue from "vue"; const a = {test1: 1, test2: 2}; const {test1, test2} = a var function b () {} let c = () = > {}; var d = () = > {}

Then online ast converts the website and copies the content to look at the generated syntax tree structure.

Let's first implement an example, such as removing useless variables from the following code

Before conversion

Var a = 1 position var b = 2 share console.log (a)

After conversion

Var a = 1 position console.log (a)

Scope.getBinding (name) gets all current bindings

Whether the scope.getBinding (name) .referenced binding is referenced

Scope.getBinding (name). ConstantViolations gets all current binding modifications

Scope.getBinding (name). ReferencePaths gets all the current binding paths

Code implementation

Const t = require ("@ babel/types"); const parser = require ("@ babel/parser"); const traverse = require ("@ babel/traverse"). Default;const generate = require ("@ babel/generator"). Default;const ast = parser.parse (`var a = 1bot var b = 2bot console.log (a); `); traverse (ast, {VariableDeclaration (path) {const {node} = path; const {declarations} = node) / / it is convenient to deal with const a = 1 declaration b = 2; this scenario node.declarations = declarations.filter ((declaration) = > {const {id} = declaration; / / const {b, c} = a If (t.isObjectPattern (id)) {/ / path.scope.getBinding (name). Referenced determines whether the variable is referenced / / removes the unused variable id.properties = id.properties.filter through filter ((property) = > {const binding = path.scope.getBinding (property.key.name); return!! binding?.referenced;}) / / if all variables in the object are not applied, the object removes return id.properties.length > 0;} else {/ / const a = 1; const binding = path.scope.getBinding (id.name); return!! binding?.referenced;}}) / / if the entire definition statement is not referenced, remove if (node.declarations.length = 0) {path.remove ();}},}); console.log (generate (ast) .code); 7. After understanding the basic processing flow, let's take a look at the final code implementation, const t = require ("@ babel/types"); const parser = require ("@ babel/parser"). Const traverse = require ("@ babel/traverse"). Default;const generate = require ("@ babel/generator"). Default;const ast = parser.parse (`import vue from 'vue'; var a = 1polivar b = 2vue'; var a var {test1, test2} = {test1: 1, test2: 2}; function c () {} function d () {} d (); console.log (a, test1); `, {sourceType: "module",}) Traverse (ast, {/ / process const var let VariableDeclaration (path) {const {node} = path; const {declarations} = node; node.declarations = declarations.filter ((declaration) = > {const {id} = declaration; if (t.isObjectPattern (id)) {id.properties = id.properties.filter ((property) = > {const binding = path.scope.getBinding (property.key.name); return!! binding?.referenced) }); return id.properties.length > 0;} else {const binding = path.scope.getBinding (id.name); return! binding?.referenced;}}); if (node.declarations.length = 0) {path.remove ();}}, / / process import ImportDeclaration (path) {const {node} = path; const {specifiers} = node If (! specifiers.length) {return;} node.specifiers = specifiers.filter ((specifier) = > {const {local} = specifier; const binding = path.scope.getBinding (local.name); return!! binding?.referenced;}); if (node.specifiers.length = 0) {path.remove ();}}, / / process function FunctionDeclaration (path) {const {node} = path Const {id} = node; const binding = path.scope.getBinding (id.name); if (! binding?.referenced) {path.remove ();}},}); console.log (generate (ast) .code); 8. Vscode sets the limit that our plug-in only supports js files

Because our current implementation is for js files, we can invalidate our shortcuts by opening other types of files. We can modify package.jsonpackage.json.

{"contributes": {"commands": [{"command": "rm-unuse-var.remove", "title": "Hello World"}], "keybindings": [{"command": "rm-unuse-var.remove", "key": "ctrl+6", "mac": "cmd+6" "when": "resourceLangId = = javascript"]}} 9. Integrate it into the project we created earlier

Omitted here. I believe that after reading the above introductions, you are fully capable of integrating on your own.

10. Package and release plug-ins

Packaged, we can use vsce tools.

Global installation of vsce

# npmnpm i vsce-g # yarnyarn global add vsce

Package plug-in

Modify the README.md file before packing or an error will be reported.

Vsce package

After execution, a .vsix file is generated.

If you want to use vscode locally, you can import it directly.

If we want to release it to the market, we need to register our account https://code.visualstudio.com/api/working-with-extensions/publishing-extension#publishing-extensions first.

# Log in to the account vsce login your-publisher-name# and publish vsce publish

After the successful release, we can see marketplace.visualstudio.com/items?itemN in our market. You can also search for our plug-ins in vscode.

The above is vscode+babel and then develop a plug-in that intelligently removes unused variables. The editor believes that there are some knowledge points that we may see or use in our daily work. I hope you can learn more from this article. For more details, please follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report