# JetBrains IDEs hidden features: Syntax Highlighting

JetBrains has added powerful improvements to their IDE over the years, but leaves some features disabled in the default configuration. If my colleagues are representative, most users don't know these features exist.

Here, we're going to look at syntax highlighting. The default schemes only assign colors to a few token types. My goal is for you to be aware of the token types that are available, and to customize more of them.

And JetBrains, I want you to help change the defaults!

# What's off?

I'll use this Java code to test out syntax highlighting in IntelliJ. But everything here applies to all JetBrains IDEs and languages.

Here's what the code looks like with IntelliJ's default light theme.

Screen Shot Default Light Theme

And here's what it looks like with my light theme.

Screen Shot Craig's Light

And here's my dark theme.

Screen Shot Craig's Dark

# TL;DR

If you just want to use my settings, you can get them here.

If you want to know what the colors mean, read on.

# Color Semantics

# Foreground colors for concrete and abstract

I use a maroon color to represent concreteness (in classes and methods) and a teal color to represent abstractness.

  • Interfaces are teal
  • Concrete classes are maroon
  • Abstract classes are maroon with a teal underline
Screen Shot concrete and abstract

Method calls are underlined with teal if the method is defined in an interface.

Screen Shot method calls

Method calls are underlined with maroon if the method is defined in a superclass.

Screen Shot superclass method call

# Italics and bold for static and mutability

I use italics to represent static.

I use bold to represent mutability.

  • Fields that are non-final, both static and non-static, are bold
  • Parameters that get reassigned are bold
  • Variables that get reassigned are bold, including loop variables
Screen Shot 2022-10-08 at 3 01 55 PM

# Background colors for errors

I use background colors to represent errors, warnings, and weak warnings.

Screen Shot errors and warnings

# Differences from defaults

IntelliJ ships with 4 predefined color schemes: Classic Light, Darcula, High contrast, and IntelliJ Light. Plugins can add more.

# Foreground colors

The default themes do not use many colors, and few token types are customized. Classes, interfaces, parameters, local variables, and method calls have no customization and are displayed as default text.

The default themes have custom foreground colors for keywords, fields, numbers, and string literals. I've kept these colors unchanged in my themes.

# Italics and bold

The default themes use italics to represent static, which I kept unchanged.

I use bold to emphasize mutability. This can help when stepping through code in the debugger. Only the bolded names can have their values change over time.

IntelliJ Light doesn't use bold. Classic Light uses bold for keywords, instance fields, and static final fields, but not static non-final fields.

Screen Shot default bold

If there is some meaning behind bold in this theme, I haven't figured it out.

# Errors and warnings

The default themes use a mix of background colors and text decorations to show errors, warnings, and weak warnings.

Screen Shot default errors and warnings

Text decorations can shadow each other.

Screen Shot underline obscured

Here, the underline for reassignment is obscured by the underwave for the type error.

# Configuration

To configure your own color scheme:

  • Open the IDE settings, go to Settings > Editor > Color Scheme.
  • Choose a built-in scheme, like IntelliJ Light or Darcula.
  • Click the gear icon, and choose Duplicate...
  • Give it a name and choose Apply.

Next it's helpful to look at a specific language. I'll click Java.

# Quick config

Clicking an element in the preview pane will jump to its token type in the color scheme editor.

Screen Shot Color Scheme Editor

(Clicking a parameter jumps to the settings for parameters.)

This makes it easy to discover the various token types, and can make it quick to set up a new color scheme. However, we usually don't want to apply our config here at the "leaves."

# Config tree

The token types that we can configure are organized into a hierarchy. Each token type either has custom display settings, or uses the settings from the parent type. The "Inherit values from" pane has a hyperlink we can click to jump to the parent type. Following one example chain:

  • Java > Constant (static final imported field)
  • Java > Constant (static final field)
  • Java > Static field
  • Language Defaults > Static field
  • Language Defaults > Default
  • General > Default text

It's best to configure the token types as high in the hierarchy as possible, in "Language Defaults" or "General" whenever possible. Settings here will apply to all programming languages, which is especially helpful when working with a new language.

Let's say we're reading Scala code for the first time, so we're not yet familiar with traits.

Screen Shot Scala Trait

We can see that the trait is highlighted teal, a strong hint that traits are similar to interfaces.

Out of the box, my theme works pretty well for Scala.

Screen Shot Scala Code

With a bit of language-specific tweaking, we can make it even better. If we can keep the tweaks to a minimum, we will have a consistent experience across languages.

# Conclusion

You already knew that JetBrains IDEs support syntax highlighting, but hopefully you learned something about how powerful the highlighting engine is. If you're already configuring your own color scheme, I'd love to see your setup.

What other features should folks know more about, where the IDE ships with them disabled by default?