Inside Visual Studio Code - Classes and Interfaces
Tags: vsc, visualstudiocode, typescript
Published: 2020-04-02 15:38:27

---
title: Inside Visual Studio Code - Classes and Interfaces
published: true
description: 
tags: vsc, visual studio code, typescript
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/5x7ga31pkev7wu2947jf.png
---

I've been trying to dive into the internals of [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=devto-blog-alvidela), so I wanted to have a tool that would let me see the names of classes and interfaces declared in VSC own [code](https://github.com/microsoft/vscode).

This tool would traverse VSC own code, load the TypeScript files defined there, and then for each file it would output something like this:

```bash
ColorPickerBody|/path/to/vscode/src/vs/editor/contrib/colorPicker/colorPickerWidget.ts
ColorPickerHeader|/path/to/vscode/src/vs/editor/contrib/colorPicker/colorPickerWidget.ts
```

Where `ColorPickerBody` and `ColorPickerHeader` are two classes defined inside `colorPickerWidget.ts`.

Yesterday I [asked](https://twitter.com/old_sound/status/1245440323590991872?s=20) on Twitter if someone knew about a tool that could extract this information from a TypeScript file. [Someone](https://twitter.com/gillchristian/status/1245444857377837056?s=20) recommended that I use [ts-morph](https://github.com/dsherret/ts-morph), which after taking a look at the examples on their docs, seemed to do just what I wanted.

So I started a new TypeScript project, npm'ed `ts-morph` and then built something like this:

```typescript
import { Project, ClassDeclaration, InterfaceDeclaration } from "ts-morph";

const project = new Project();
project.addSourceFilesAtPaths("../vscode/src/vs/**/*.ts");

const sourceFiles = project.getSourceFiles();

for (let f of sourceFiles) {
    let fileName = f.getFilePath();
    let classDeclarations = f.getClasses();
    let interfaceDeclarations = f.getInterfaces();
    
    for (let c of classDeclarations) {
        console.log(`${c.getName()}|${fileName}`);
    }

    for (let i of interfaceDeclarations) {
        console.log(`${i.getName()}|${fileName}`);
    }
}
```

Let's see that in detail. First we import the required types from `ts-morph`:

```typescript
import { Project, ClassDeclaration, InterfaceDeclaration } from "ts-morph";
```

Then we create a new project, and we add source files to it. In this case we asume the location of the VSC repo–of course you could provide this as a CLI argument.

```typescript
const project = new Project();
project.addSourceFilesAtPaths("../vscode/src/vs/**/*.ts");
```

We are going to traverse those files to extract class and interface definitions. We do that by calling `project.getSourceFiles()`, which returns an array of `SourceFile`. [SourceFile](https://github.com/dsherret/ts-morph/blob/85a173fd7102585fcc1ad2c8335716160ee0d4ea/docs/details/source-files.md) is a class that can return a lot of information about a TypeScript file, from it's file name, to the imports declared there, and so on. 

Once we have the `SourceFiles[]` we are going to iterate it, to output the information we need:

```typescript
for (let f of sourceFiles) {
    let fileName = f.getFilePath();
    let classDeclarations = f.getClasses();
    let interfaceDeclarations = f.getInterfaces();
    
    for (let c of classDeclarations) {
        console.log(`${c.getName()}|${fileName}`);
    }

    for (let i of interfaceDeclarations) {
        console.log(`${i.getName()}|${fileName}`);
    }
}
```

As you can see each `SourceFile` can tell us about its name, via `f.getFilePath()`, and also return the declared classes and interfaces via `f.getClasses()` and `f.getInterfaces()` respectively.

We use two for loops, where we output the information in the following format: `className|fileName`, or `interfaceName|fileName`.

And that's it, after we compile the project, we can run it from the CLI and get the information we want:

```typescript
IStaticExtension|/path/to/vscode/src/vs/workbench/workbench.web.api.ts
ICommontTelemetryPropertiesResolver|/path/to/vscode/src/vs/workbench/workbench.web.api.ts
IExternalUriResolver|/path/to/vscode/src/vs/workbench/workbench.web.api.ts
TunnelOptions|/path/to/vscode/src/vs/workbench/workbench.web.api.ts
```

You might have been wondering why I want the information output in that format. I want to be able to pass this file to bash's `sort` and have an easy way to see which class & interface definition name are repeated across the project. 

Why? Soon I'll write another article explaining why.