JetBrains Platform
Plugin and extension development for JetBrains products.
An Interview With Scott McKinney, Author of the Manifold Plugin
Today we are speaking with Scott McKinny of Manifold Systems (scott@manifold.systems,) the author of the Manifold plugin for IntelliJ Platform-based IDEs. As a Java compiler plugin, Manifold adds new capabilities directly and seamlessly to the Java language such as type-safe metaprogramming, extension methods, operator overloading, and more.
Welcome to the JetBrains Platform Blog, Scott. Before we discuss the plugin, would you tell us a bit about yourself and your background?
Most of my programming experience is rooted in tooling. It goes way back to my employment with Borland beginning in 1991, building a product called ObjectVision. That “visual” programming language was Borland’s first foray into the Windows operating system; back then, Windows piggybacked on 16-bit DOS!
From there, I bounced around a bit until Paul Allen’s company, Asymetrix, purchased a project that a small group of us at Borland had started under Philippe Kahn’s guidance. That was interesting. Shortly after, I went to Netscape to work on browser bits and help design their next-generation browser platform.
As Netscape began to fragment, I left to start an analytics software company with a former Borland colleague. The technology we built was acquired a year later and involved a three-year employment contract, which ended abruptly due to the dot-com bust.
I took a long break before I joined a fresh startup, Guidewire, in early 2002. Over the course of several years there, and with the help of some incredibly talented people, I created the Gosu programming language. Most of what Manifold has become today can be attributed to the lessons I learned designing and building that language.
Tell us about the Manifold plugin; how did it come to be, and what are the features?
Manifold is a Java compiler plugin and framework designed to expand the reach of Java’s type system to directly connect in a type-safe way to information sources such as GraphQL, JSON, XML, SQL, Javascript, and just about any type of resource imaginable.
The Manifold plugin also enhances Java with productivity features, including extension methods, operator overloading, unit expressions, type-safe reflection, templates, a preprocessor, and more. The IntelliJ Platform plugin provides comprehensive support in both IntelliJ IDEA and Android Studio.
Details for specific features are available on the Manifold website and GitHub repo. The most popular features so far include:
The GraphQL Manifold
Use types defined in *.graphql
files directly from your Java code. No code generator steps, no POJOs or data classes, and no superfluous in-language DSLs. Make GraphQL changes and immediately use them with code completion, navigation, find usages, refactor, etc. Here is an example of using GraphQL files to define a movies type, and for queries about them.
Extension Methods
You can add methods to existing classes, including those you do not control, such as JRE classes like String
, List
, etc.
@Extension
public class MyStringExtension {
// Add print() instance method to String via @This
public static void print(@This String thiz) {
System.out.println(thiz);
}
}
// Use the method directly on String
"Hello World!".print();
Operator Overloading
Type-safety provides arithmetic, relational, and unit operators for any class by implementing one or more predefined operator methods. You can implement operator methods directly in your class or use extension methods to implement operators for classes you don’t otherwise control. For example, Manifold uses extension methods to provide operator implementations for BigDecimal
so you can write code like this:
BigDecimal result = bigValue1 + bigValue2;
Here’s a simple example demonstrating how to implement the +
operator:
public class Point {
public final int x, y;
public Point(int x, int y) {this.x = x; this.y = y;}
// implement `+`
public Point plus(Point that) {
return new Point(x + that.x, y + that.y);
}
}
var a = new Point(1, 2);
var b = new Point(3, 4);
var sum = a + b; // Point(4, 6)
Unit Expressions
Unit expressions are unique to the Manifold framework. They provide a powerfully concise syntax and can be applied to a wide range of applications. For instance, the unit operator enables concise, type-safe expressions of quantities:
Mass weight = 65 kg;
Length distance = 70 mph * 3.5 hr;
Money payment = 1.5M USD;
Force f = 5.2 kg m/s/s; // same as 5.2 N
The Preprocessor
Use familiar directives such as #define
and #if
to conditionally compile your Java projects. The preprocessor offers a simple and convenient way to support multiple build targets with a single codebase.
Type-safe Reflection with @Jailbreak
Sometimes you have to use Java reflection to access fields, methods, and types that are not directly accessible from your code. Writing reflection code is not only tedious and error-prone but also loses type-safety in the process. Manifold mitigates these issues with the @Jailbreak
annotation and the jailbreak()
extension method. Use them to leverage the Java compiler’s convenience and type-safety and let Manifold generate reliable, efficient reflection code for you.
Annotate the type of any variable with @Jailbreak
to gain direct, type-safe access to private fields, methods, and types.
@Jailbreak Foo foo = new Foo(1); // foo has access to private stuff!
foo.privateMethod();
foo.privateMethod("hey");
foo._privateField = 88;
Templates
You can author Manifold template files (*.mtl
) with Java’s full expressive power and use them in a type-safe way directly in your code. Templates support type-safe inclusion of other templates, shared layouts, and a lot more.
String Interpolation (aka String Templates)
A String template lets you use the $
character to embed a Java expression directly into a String. You can use $
to embed a simple variable.
int hour = 8;
String time = "It is $hour o'clock"; // prints "It is 8 o'clock"
Or you can embed an expression of any complexity in curly braces:
LocalTime localTime = LocalTime.now();
String ltime = "It is ${localTime.getHour()}:${localTime.getMinute()}";
// prints "It is 8:39"
What was your motivation for creating the Manifold plugin?
The cool factor of type-safe metaprogramming is hard to beat. Implementing that feature in the IntelliJ Platform involved a pile of work. However, it is the feature I am most proud of. It is a truly groundbreaking framework that bridges the gap between software and information. There’s lots of potential.
I’d say either Manifold Templates or the type-safe metaprogramming were the most challenging features. Implementing templates in the IntelliJ Platform was challenging, mostly because I had to learn so much along the way. The feature is basically a type-safe, modernized version of JSP you can use anywhere in your Java project, kind of a huge undertaking to implement all that.
The productivity potential offered by IntelliJ IDEA is incredible and is, in my view, categorically unmatched. So it should come as no surprise that the Manifold project does not release a single feature without first building comprehensive support in IntelliJ IDEA.
I’d estimate the time invested in the initial release is in the ballpark of one to two years of full-time work. Of course, the plugin is a perpetual work in progress.
What is the current state of the plugin, and what are the plans for its future?
Most recently, I’ve been building out support for Manifold on Android Studio. This platform is still in the experimental phase for Manifold; however, much of it is complete and available for use.
Kotlin support is another recent feature. Although Manifold is a Java compiler plugin, its type-safe metaprogramming capabilities, such as with GraphQL, can be used for other JVM languages like Kotlin. I’m excited about the prospects for both of these new features as they broaden Manifold’s horizons.
What’s next for the Manifold plugin? There’s a lot on my pile of things I want to do! After Android support stabilizes, I plan to begin working on a SQL type manifold, which will type-safely bridge Java to SQL, similar to how the GraphQL manifold works. Of course, plans can change, so I never really know what I’ll be doing a month from now.
Can you tell us what you liked about the plugin development process and what could be improved?
I’ve been working with the IntelliJ Platform for quite a while, going back at least twelve or so years building plugins. Like the IDE product itself, the IntelliJ Platform is amazing and a joy to work with. Practically every aspect of the IntelliJ Platform can be configured, extended, or completely replaced.
I suppose it goes without saying, but the IntelliJ Platform is the clear market leader; the benefits as a platform are obvious. Apart from that, after working with Eclipse/JDT, there is no comparison between them; the IntelliJ Platform architecture is immensely more capable and flexible.
The JetBrains Marketplace is superb, too. It takes care of the business end so plugin developers can focus on what they do best. JetBrains is always a pleasure to work with; they are always honest, courteous, and respectful.
Scott, thank you for talking with us today about the Manifold plugin for IntelliJ Platform-based IDEs.
If people want more information, they can visit the Manifold Marketplace page, the Manifold website, or the GitHub repository.