IntelliJ IDEA
IntelliJ IDEA – the Leading Java and Kotlin IDE, by JetBrains
Salesforce development plugins, part 1 — Illuminated Cloud
Today we’re starting a 2-part series of guest posts from the creators of IntelliJ IDEA plugins for Salesforce (or Force.com) developers. The plugins are Illuminated Cloud 2 and JetForcer.
Please meet the 1st blog post by Scott Wells, the developer of Illuminated Cloud. And do not miss the second post that covers JetForcer plugin.
In late 2010, I started leading our product engineering organization in the transition from a traditional on-premise Enterprise-style software model to a modern SaaS-based model. After a short evaluation of existing PaaS, SaaS, and IaaS offerings, we determined that the Salesforce App Cloud Platform-as-a-Service (then called Force.com) would play a key role in our SaaS product architecture.
For our purposes, Salesforce had effectively packaged many of the complex and expensive aspects of a SaaS offering including multitenancy, security, scalability, and pervasive metadata-based configurability. As we started our implementation in earnest, we learned that they had not, however, successfully addressed the all-important aspect of developer tooling.
A Productivity Paradox
One of the key ways that Salesforce has been able to offer a secure metadata-based multitenant platform is by creating their own technologies for business logic (Apex), data access and manipulation (SOQL and SOSL), and presentation tier development (Visualforce and, more recently, Lightning). While these technologies are clearly inspired by more established mainstream development platforms—Apex’s syntax owes a heavy debt to Java, and SOQL is very similar to ORM query languages such as HQL and JPQL—these technologies are explicitly tailored for execution in a secure, governor-limited, multitenant runtime with a very tight-coupling between persisted data and its supporting business logic.
The Salesforce development model is also quite different in that there is no available local runtime execution environment. All source code—along with all other metadata—must be deployed into a Salesforce organization (basically a single tenant “slice” of the Salesforce multitenant runtime) and executed via some type of request. Requests can take multiple forms including UI interactions, API requests, scheduled processes, and unit test execution.
In late 2010/early 2011, very little developer tooling support existed for Salesforce’s programming languages and development model, and what did exist was exceptionally primitive. Salesforce offered the Force.com IDE, an Eclipse plugin with rudimentary syntax highlighting and auto-indentation capabilities as well as the ability to manage the transfer of Salesforce metadata back and forth between the local filesystem and the Salesforce organization. The development community had also implemented plugins and scripts other editors, though features were similarly limited. Having spent over a decade using full IDEs such as IntelliJ IDEA, the existing options seemed primitive and quite limiting. Many of the productivity gains promised by building atop the Salesforce PaaS were being eroded due to the immature state of its tooling.
In Search of a Solution
Developer tooling has always been a passion for me. I’ve always enjoyed creating tools—APIs, scripts, and a few times even plugins for whatever tool I happened to be using at the time—that help increase not just my own productivity but also that of my teammates. As a result, I found myself frequently looking for ways to address this lack of mature tooling for our chosen technology foundation. In the absence of a real code formatter, and with developers applying a myriad of tools to our source files, our code base was becoming utterly chaotic. I tried to adapt existing command-line code formatters to the Apex grammar with varying levels of success. I modeled a custom file type in IntelliJ IDEA for Apex and associated it with the respective source file extensions. I then created external tools for our ant-based command-line metadata deployment and retrieval scripts and added them to the keymap. We could now work in the same IDE we used for Java development, albeit without even simple IDE features such as code completion, a formatter, or reference navigation. It was an improvement, but it was far from a true IDE for what was becoming nearly half of our code base.
A Solution Found
In early 2013, I found myself with some downtime and used it to explore the IntelliJ IDEA plugin SDK, specifically the notion of custom language plugins. Salesforce does not currently publish grammars or language specifications for Apex, SOQL, SOSL, or their presentation tier expression languages. I started by creating a custom grammar for Apex based primarily on the published grammar for Java 5, adding and removing rules based on the differences between Apex and Java. In short order I had a very simple plugin that could effectively replace the custom file type for syntax highlighting, very simple formatting, and keyword completion. However, as it’s prone to do, life got in the way and the project was shelved. A little over a year later I decided to revisit the project. Over the next several months I steadily added features to the plugin including a structure view, code folding, simple identifier code completion, and simple reference injection and navigation. I shared the plugin with my team, and we began to use it as our primary Salesforce development tool.
In late 2014, a few people asked whether they might contribute to the project. This spurred an unexpected internal debate over whether I might instead want to shape the plugin into a commercial offering. After a brief period of introspection and discussion with my family and friends, I decided to pursue the commercial direction. Little did I know how much work that would require, and in particular just how much of that work would have absolutely nothing to do with writing code. Nor could I have known how incredibly rewarding it would be to create something that can so positively impact developers’ day-to-day work.
In June 2015, I released Illuminated Cloud. In the two-and-a-half years since the initial release, I’ve continuously enhanced the feature set based on both my own priorities as a daily user of the product and the incredible community feedback received via the public issue tracker, discussion groups, direct email contact, and in-person interactions at industry conferences and regional user group meetups. I’ve received enthusiastic support from both Salesforce and JetBrains as I’ve integrated key features of the former into the corresponding first-class plugin SDK extension points exposed by the latter. Illuminated Cloud has been enhanced to support new Salesforce technologies such as Lightning, a presentation tier technology, and Salesforce DX, a developer experience platform (and philosophy).
The implementation of Illuminated Cloud has presented many technical challenges. Not only are there no published grammars or language specifications for Salesforce’s languages, but there is also no formal SDK for Apex. In fact, each organization has a unique SDK based on its enabled features and customizations. To overcome this omission, at the heart of Illuminated Cloud is the Offline Symbol Table, a high-fidelity, organization-specific SDK for Salesforce development generated using the Salesforce APIs with extensive tweaks and corrections based on other resources, both documented and undocumented. Without the Offline Symbol Table, it would be virtually impossible to implement the pervasive real-time expression type inference which is so critical to IDE features such as contextually-aware code completion, reference tracking and navigation, integrated API documentation, refactoring, and real-time static code analysis.
The reception to Illuminated Cloud by the amazing Salesforce developer community has been nothing short of incredible and is easily my favorite aspect of this entire endeavor. The feedback I receive from users, both positive and critical, is invaluable in the ongoing evolution of the product’s feature set. As someone with a passion for developer tooling, this experience has truly been a dream come true.
The Next Generation
Since starting Illuminated Cloud, my end goal has always been to minimize the feature gap between IntelliJ IDEA for Java development and Illuminated Cloud for Salesforce development. The first major version of the product included contextually aware code completion for all of Salesforce’s languages, pervasive reference tracking and navigation, powerful live templates for Apex and SOQL, integrated unit testing and code coverage, ad hoc Apex and SOQL script execution, an integrated log viewer, a log-based post-mortem debugger, integrated API documentation, and much more. However, it was still lacking many of the modern features that make tools like JetBrains’ IDEs seem nearly magical—in particular refactoring, real-time static code analysis and automated fixes, intelligent code generation, and type inference-based code completion. I decided that those features would form the structure of the second major version of the product.
In December 2017, I released Illuminated Cloud 2 with all of the features of Illuminated Cloud plus:
- WebStorm support – In addition to IntelliJ IDEA, Illuminated Cloud 2 fully supports WebStorm, extending its HTML, JavaScript, and CSS editors for best-in-class development of Salesforce Lightning and Visualforce applications.
- Refactoring – Illuminated Cloud 2 includes rename, extraction, inline, safe delete, copy, and move refactorings.
- Code inspections and intentions – Illuminated Cloud 2 includes many code inspections to help ensure code validity without the need for a server round trip, to identify and eliminate unused source code, and to help manage standards compliance across the code base.
- Code generation – Illuminated Cloud 2 automatically generates correct implementations of unimplemented methods from base classes and interfaces.
As always, I’m constantly enhancing the product’s feature set. New and enhanced refactorings, code inspections and intentions, and intelligent code generation capabilities are released on a frequent basis. Very shortly I will be adding full support for smart completion in Apex so that offered code completions can be filtered based on the expected data types. I also intend to integrate the Apex Debugger to facilitate interactive debugging of live requests.
With so many of IntelliJ IDEA’s features now present in Illuminated Cloud 2, I often find myself reaching for a feature that’s not yet implemented. When that happens, I use that as key input into my backlog’s list of features and their relative prioritization.
As both the developer and a daily user, I’m extremely excited about the new version of Illuminated Cloud and how it allows Salesforce developers to truly own and evolve their product source code. It certainly represents a huge shift from the productivity paradox of just a few years ago.