Michael Müller
05 May, 2023

SemanticDiff 0.8.3: Support For Go And More

The third beta release of SemanticDiff adds support for comparing Go files, improves nearly all supported programming languages, and increases the speed as well as the accuracy.

We have just released version 0.8.3 of our Visual Studio Code extension SemanticDiff. This update introduces support for Go, which means you can now get programming language aware diffs that hide style-only changes for your .go files as well.

Besides the addition of a new language, this release brings improvements to the existing languages as well as visual changes. So even if you do not use Go, be sure to update to version 0.8.3. As usual, Visual Studio Code should install the update automatically, but if it doesn’t or you haven’t downloaded it yet, here’s the link to the Marketplace:

Download Beta

Go Support

As mentioned in the introduction, SemanticDiff 0.8.3 introduces support for generating programming language aware diffs for Go. What this means in practice is that you can now reformat your code with gofmt and SemanticDiff should display an empty diff as it ignores style-only changes. This is especially useful if your files also contain other modifications that would be easily missed in a standard diff amidst all the format changes.

If you haven’t used SemanticDiff yet, here is a screenshot of a toy example to demonstrate what this looks like:

Go code changes in SemanticDiff

On the right side a new parameter has been added, while the existing ones have been split into several lines. SemanticDiff highlights only the newly added parameter and indicates that the old line is mapped to multiple lines in the new code.

This toy example shows only a subset of the supported features. The full list of invariances (i.e. changes that are not displayed in the diff) include:

  • Adding/Removing whitespaces or line breaks outside of strings and comments
  • Adding/Removing optional commas
  • Adding/Removing unnecessary parenthesis
  • Reordering of type elements in a type term (e.g. [T int|string] = [T string|int])
  • Exchanging escaped characters in a string/rune with an equivalent representation (e.g. the literal)

This doesn’t cover all the code transformations of gofmt yet, but we wanted to make sure everything is parsed correctly before adding more features. So reporting any parsing failures you encounter or spreading the word about SemanticDiff so more people can test it would help us a lot 🙂.

As with any other supported language, SemanticDiff can also detect and highlight moved code blocks in Go:

Moved Go code in SemanticDiff

Improved Parsing

Since correctly parsed code is the basis for all our features, we spent some time to update our existing parsers to include newer language features and to fix some bugs. Here is an overview of the various changes per language:

More Compact Display Of Changes

This release changes how a diff is rendered when one line in the old code corresponds to multiple lines in the new code (or vice versa). For the explanation we will use the following TypeScript example, where line 1 in the old code corresponds to lines 1-5 in the new code:

TypeScript example in SemanticDiff

So far, we have always displayed the old line “in sync” with the first line of the new code block. This means that both lines take up the same amount of vertical space. You can see this when we make the window smaller so that the text of the old line wraps around:

Old line wrapping in SemanticDiff

This gives the impression of an empty line in the new code, which is misleading and makes the code harder to read. Especially if the code contains many long lines, or if they wrap over more than 2 “lines”. Since we know that there is no 1:1 relationship between the lines anyway, we decided to change this behavior. We now allow the old line to take up as much vertical space as all the new lines it maps to:

New line wrapping in SemanticDiff

Even though this is a small change, we hope it will help you review code even faster with SemanticDiff.

Other Improvements

The remaining changes were focused on improving the speed and accuracy of SemanticDiff. To ensure that SemanticDiff never hides any actual changes from a user, we are rather conservative in which invariances we add and how the old code is matched with the new code. As with every release, we have continued to fine-tune this behavior and improve our algorithms. Many of these changes would be too technical for a release note and are not very interesting to read either. However, there is one small change that is easy to explain though.

Similar to Go, we consider adding or removing unnecessary parenthesis in JavaScript and TypeScript to be an invariance. There was one case we missed so far: Adding/removing the parenthesis around the only parameter of an arrow function. This is now fixed and SemanticDiff will treat the following two codes as identical:

const foo = (x) => x;
const foo = x => x;

Next Steps

We recently conducted a survey among our newsletter subscribers, asking them what blockers they encounter and letting them vote on our next features. It turned out that support for Go and Rust was one of the most frequently mentioned blockers. Now that Go is fixed, we are looking into adding support for Rust in one of our next releases. If you would like to participate in these votes, be sure to subscribe to our newsletter.

We hope you enjoyed this update!

Recent Articles

SemanticDiff vs. Difftastic: How do they differ?
SemanticDiff vs. Difftastic: How do they differ?

Both tools aim to provide a better diff, but which one fits your needs? We compared their inner workings, features, and workflow integration to help you decide.

Read More
Unicode tricks in pull requests: Do review tools warn us?
Unicode tricks in pull requests: Do review tools warn us?

How well do GitHub, GitLab and Bitbucket support reviewers in finding malicious code changes in pull requests? Let’s give it a test.

Read More
SemanticDiff 0.8.8: Support For Rust And More
SemanticDiff 0.8.8: Support For Rust And More

The eight beta release of our VS Code extension / GitHub App SemanticDiff adds support for Rust, new invariances and other enhancements.

Read More