Learn more about Unused Entities Information & Warnings

In this post we’re looking at the unused entities information and how to configure warnings for it. This is one of many ways Sw!ftalyzer helps us finding potential areas of improvement in our app.

Getting an Overview of Unused Entities with Sw!ftalyzer

When removing an old and unused feature or refactoring code, it’s easy to miss that some part of the code stays in the project although it’s no longer in usage. Later on its often time consuming to find and remove unused code. But keeping code entities around longer than needed can slow down development.

Sw!ftalyzer automatically analyses all dependencies and can find entities without any incoming dependencies. Although these entities are not necessarily unused, they are a good starting point for checking and removing unused code.

We’ll use a demo project analysis to see how this looks like. Download the analysis file and open it in Sw!ftalyzer to explore the analysis: DemoProject

This project contains two files, DemoProjectApp.swift and ContentView.swift. The first one includes the declaration of DemoProjectApp. This struct is the main entry point of the app.

@main
struct DemoProjectApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

This is the code for the second file, there are four different entities:

struct ContentView: View { /* ... */ }

struct ContentView_Previews: PreviewProvider { /* ... */ }

protocol LegacyService { }

class OldViewController: NSViewController { }

The struct DemoProjectApp has a dependency to ContentView, same is true for ContentView_Previews. The protocol LegacyService and the class OldViewController are never used. Most probably they are a left-over from a previous refactoring.

This is how Sw!ftalyzer visualises the dependency graph:

A graph showing the files and entities of the demo project. Arrows between entities show dependencies between them.
Dependency graph of the demo project.

We can see the code entities and their dependencies. There are two arrows pointing from DemoProjectApp and ContentView_Previews to ContentView. This shows us, that these two entities use the struct ContentView. No arrow leads to the protocol LegacyService and the class OldViewController.

The dependency graph is a great way of getting an overview of our code entities and the dependencies between them. Another way of finding this information is in the information panel to the right of the graph.

We can get a list of unused entities when selecting the third tab in the right panel, which is highlighted in the image. This tab shows general project information independent from the currently selected node.

A screenshot of Swiftalyzer with the 4 tabs of the information panel. The third one is selected. A red border highlights the third tab.
The third tab shows general information about the project.

Among other things, we can find a list of unused entities here. For the demo project it shows the entities DemoProjectApp, LegacyService and OldViewController.

This list doesn’t contain the entity ContentView_Previews, although it has no incoming dependency. Previews are generally not referenced by other entities and are stand-alone. Thus Sw!ftalyzer ignores them when listing unused entities.

A screenshot from Swiftalyzer showing a list of entity names that have no incoming dependency and thus are probably unused. The list names the entities DemoProjectApp, LegacyService and OldViewController.
A list of entity names makes it easy to find unused entities.

There may be good reasons to keep dead code around, e.g. to use it as a reference later on. In case we want to accept that an entity is unused without seeing warnings about it, or if the warning is a false positive, we can ignore the finding.

It may also be that an entity has no incoming dependency in the analysed module. But there can still be code in another module not included in the analysis that uses this entity. So always be careful when removing an entity.

In this example, DemoProjectApp is important, although it has no incoming dependency. Thus we want to ignore it in this list. To do so, we open a context menu via a right click on the dark grey box. This context menu has an item to ignore finding. The next picture shows how this looks like after ignoring the finding for the entity DemoProjectApp.

A finding can be un-ignored again by opening the context menu again and clicking on the item to un-ignore it.

A similar screenshot to the one before from Swiftalyzer showing a list of potentially unused entities. The list names the entities DemoProjectApp, LegacyService and OldViewController. The item for DemoProjectApp is ignored and shown with a slightly different color at the bottom of the list.
An ignored item looks different then an un-ignored item and is placed at the bottom of the list.

Configuring Warnings about Unused Entities

Warnings are a great way of quickly finding areas of improvement in our apps. A class with a warning has a red bubble in the upper right corner of the node that shows the number of warnings.

We can configure warnings in the configuration tab. It’s the fourth tab in the right panel, which is highlighted in the image. Select it to see options for various warnings, like the warning about unused entities below.

A screenshot of Swiftalyzer with the 4 tabs of the information panel. The last one is selected. A red border highlights the fourth tab.
Configure warnings in the fourth tab of the right panel.

There’s a checkbox to enable or disable the warning. When enabled, Sw!ftalyzer shows a warning for each entity node without incoming dependency. It’s selected by default.

Unselecting this checkbox removes all warnings about unused entities in the dependency graph.

A checkbox allows to enable or disable warnings about unused entities in the dependency graph. The checkbox is enabled.
Enabling or disabling warnings via the checkbox.

With the unused entities warning enabled, we see indicators at the same nodes as we’ve seen in the list before:

A similar graph as above showing the files and entities of the demo project. Arrows between entities show dependencies between them. In addition, the nodes representing the protocol LegacyService, the class OldViewController and the struct DemoProjectApp have red bubbles in the top right corner with the number 1. This means that there is one warning for each of these entities.
The graph shows warnings for entities that are not used by any other entity.