JetBrains IDEs hidden features: Syntax Highlighting

Craig Motlin
5 min readOct 12, 2022

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.

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

And here’s my dark theme.

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

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

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

Italics and bold for static and mutability

I use italics to represent static.

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

  • 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

Background colors for errors

I use background colors to represent errors, warnings, and weak 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.

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

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.

Errors and weak warnings use underwaves. Warnings use a background color.

Text decorations can shadow each other.

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 on the bottom will jump to its token type in the color scheme editor on top.

Clicking param1 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” of the tree.

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 not too familiar with Scala code and we come across a trait.

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

Out of the box, my themes work pretty well for Scala.

With a bit of language-specific tweaking, we can make our themes 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.

See my other post if you’d like to know more about how I picked specific colors.

What other features are chronically underused, because the IDE has them disabled by default?

--

--