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:
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:
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:
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:
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:
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:
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!