SlideShare a Scribd company logo
Taking ReSharper
out of process
Matt Ellis
@citizenmatt
Rider - Taking ReSharper out of Process
Why build a .NET IDE now?
How do you build a .NET IDE?
How do you build a 

cross platform .NET IDE?
How do you build a 

cross platform IDE?
Rider - Taking ReSharper out of Process
Hello IntelliJ
Hello IntelliJ IDEA
Hello IntelliJ Platform
https://github.com/JetBrains/intellij-community
Uh-oh. JVM
How do you build a .NET IDE in the JVM?
Options?
Rider - Taking ReSharper out of Process
ReSharper out of process
• Language server
• Headless. Command line process. IntelliJ provides the UI

Client/server communication
• Cross platform

.NET Framework on Windows. Mono on MacOS and Linux
• Removes Visual Studio in-process constraints

Memory usage. 64 bit
• Continued investment in ReSharper
Thick Client? Thin Client?
• IntelliJ provides high level UI elements, functionality and infrastructure

Editors, Alt+Enter, completion, Find Usages, test runner, debugging…

Searchable tree views, popup dialogs, settings pages…
• No knowledge of syntax trees or semantic model

Parsing, resolving, syntax highlighting, folding, inspections, refactoring,
code completion, etc. all owned by ReSharper
• (Some standalone functionality)

Find in path, REST client, Databases, VCS
• Optimisations

Lexing for initial syntax highlighting
Rider - Taking ReSharper out of Process
Alt+Enter
• IntelliJ provides editor, text caret, and tracks Alt+Enter keypress
• Asks current language for items
• Current language is an IntelliJ facade for ReSharper out-of-proc

Asks ReSharper for items at current location
• ReSharper returns list of display names, icons and submenus
• IntelliJ displays items in Alt+Enter menu
Inspection highlights
• IntelliJ provides infrastructure to display “squigglies”
• Opposite direction, pushed from ReSharper
• Source file is opened, or modified

IntelliJ notifies ReSharper
• ReSharper analyses the file, runs inspections, gathers highlights
• ReSharper publishes list of range, severity and tooltip
• IntelliJ displays squiggles
Modifying source
• Bi-directional
• User typing

IntelliJ publishes changes as delta of typed characters at offset
• ReSharper rewriting code

Publishes delta as chunk of code

Renamed variable, new method, additional `using` statement, etc.
Observations
• Enabling functionality, rather than implementing it

Can show all Alt+Enter menus, run all inspections, rewrite code in
context actions and quick fixes
• As long as there is no UI…
• The data is very lightweight
IPC - RPC?
• Boilerplate - define calls and messages for each required action
• Imperative
• Conflict resolution?

Who wins? How to reset/resync state?
• JSON? Protobuf?
Client

(IntelliJ)
Server

(ReSharper)
MVVM
• Only send data required for UI components
• Lightweight View Model data
View

(IntelliJ)
Model

(ReSharper)
View

Model
Hierarchical View Model
Shared View Model
• Single view of state of entire IDE

Shared between front end and back end

Keep in sync. Only need to update changed fields
• Becomes declarative

No more boilerplate messages, just update View Model
• Reactive/observable. Composable

Subscribe for changes
• Two way

Client and server can both contribute to View Model

E.g. button click/refactoring results
• Tightly coupled? 🤔
Conflict resolution
• The client is always right
• Each value has a version
• Version increments only when client changes value
• If server changes value, no version update
• Only accept change with same or newer version
“foo”/1
“foo”/1
“bar”/2
“bar”/2
“quux”/2
“quux”/2
“wibble”/3 “blah”/2
“wibble”/3
Client
(IntelliJ)
Server
(ReSharper)
Wire protocol
• Becomes trivial - no messages, just deltas

Don’t change the protocol, just extend model
• Supports batching
• Serialisation by code generation via DSL
• Binary wire protocol, with logging
• Sockets
Rider Framework
• Two libraries, C# and Kotlin

Provides primitives and handles communication
• Kotlin based DSL to describe View Model
• Generates real code - C# and Kotlin

Interfaces, implementation and serialisation
• Business logic subscribes to and manipulates “real model”

Magic happens
View Model building blocks
• Lifetime
• Signals (events)
• Properties (observable value)
• Maps (observable collections)
• Fields (immutable)
• Call (async RPC)
• string
• int
• enum
• classdef (node)
• structdef (data)
Lifetime
class Lifetime {
static Lifetime Eternal;
void Add(Action action);
}
class LifetimeDef {
ctor(Lifetime parent);
Lifetime Lifetime;
void Terminate();
}
Dual of IDisposable
Signal
// Produce event
interface ISource<T> {
void Fire(T value);
}
// Subscribe to event
interface ISink<T> {
void Advise(Lifetime l, Action<T> handler);
}
// Composable event
interface ISignal<T> : ISource<T>, ISink<T> {
}
Properties
// Subscribe to event
interface ISink<T> {
void Advise(Lifetime l, Action<T> handler);
}
// Observable property
interface IProperty<T> : ISink<T> {
T Value { get; set; }
void View(Lifetime l, Action<Lifetime, T> action);
}
Stateful signal
Maps
class MapEvent<K,V> {
enum Kind { Add, Remove }
Kind kind;
K key;
V value;
}
// Observable collection
interface IViewableMap<K,V>
: IDictionary<K,V>, ISink<MapEvent<K,V >> {
void View(Lifetime l, Action<Lifetime, K, V> action);
}
Kotlin DSL
fun classdef (
name : String,
init : ClassdefNode.() -> Unit
)
classdef (
“Foo”,
{
myClassdef.map(…)
	 }
)
classdef (
“Foo”,
{
map(…)
}
)
Kotlin DSL
fun classdef (
name : String,
init : ClassdefNode.() -> Unit
)
classdef (
“Foo”,
{ lambda_expression }
)
classdef (“Foo”) {
lambda_expression
}
object Solution {
init {
map(“editors”, string, classdef(“Editor”) {
list(“document”, char)
property(“caret”, int)
map(“highlighters”, Range, Highlighter)
property(“completion”, Completion.nullable)
})
voidSource(“build”)
}
val Range = classdef(“Range”) {
field(“start”, int)
field(“length”, int)
}
val Highlighter = classdef(“Highlighter”) {
…
}
}
Challenges
• Rider’s Project Model very different to IntelliJ

Replace Project view with Solution Explorer

IntelliJ uses “project” where we expect “solution”
• What about duplicate language implementations?

E.g. JavaScript - WebStorm or ReSharper?

C++ CLion or ReSharper?
• Plugins are more complex

Front end and back end
• ReSharper out of process with Visual Studio? 🙊
Thanks!
Matt Ellis
@citizenmatt
www.jetbrains.com/rider

More Related Content

Rider - Taking ReSharper out of Process

  • 1. Taking ReSharper out of process Matt Ellis @citizenmatt
  • 3. Why build a .NET IDE now?
  • 4. How do you build a .NET IDE?
  • 5. How do you build a 
 cross platform .NET IDE?
  • 6. How do you build a 
 cross platform IDE?
  • 13. How do you build a .NET IDE in the JVM?
  • 16. ReSharper out of process • Language server • Headless. Command line process. IntelliJ provides the UI
 Client/server communication • Cross platform
 .NET Framework on Windows. Mono on MacOS and Linux • Removes Visual Studio in-process constraints
 Memory usage. 64 bit • Continued investment in ReSharper
  • 17. Thick Client? Thin Client? • IntelliJ provides high level UI elements, functionality and infrastructure
 Editors, Alt+Enter, completion, Find Usages, test runner, debugging…
 Searchable tree views, popup dialogs, settings pages… • No knowledge of syntax trees or semantic model
 Parsing, resolving, syntax highlighting, folding, inspections, refactoring, code completion, etc. all owned by ReSharper • (Some standalone functionality)
 Find in path, REST client, Databases, VCS • Optimisations
 Lexing for initial syntax highlighting
  • 19. Alt+Enter • IntelliJ provides editor, text caret, and tracks Alt+Enter keypress • Asks current language for items • Current language is an IntelliJ facade for ReSharper out-of-proc
 Asks ReSharper for items at current location • ReSharper returns list of display names, icons and submenus • IntelliJ displays items in Alt+Enter menu
  • 20. Inspection highlights • IntelliJ provides infrastructure to display “squigglies” • Opposite direction, pushed from ReSharper • Source file is opened, or modified
 IntelliJ notifies ReSharper • ReSharper analyses the file, runs inspections, gathers highlights • ReSharper publishes list of range, severity and tooltip • IntelliJ displays squiggles
  • 21. Modifying source • Bi-directional • User typing
 IntelliJ publishes changes as delta of typed characters at offset • ReSharper rewriting code
 Publishes delta as chunk of code
 Renamed variable, new method, additional `using` statement, etc.
  • 22. Observations • Enabling functionality, rather than implementing it
 Can show all Alt+Enter menus, run all inspections, rewrite code in context actions and quick fixes • As long as there is no UI… • The data is very lightweight
  • 23. IPC - RPC? • Boilerplate - define calls and messages for each required action • Imperative • Conflict resolution?
 Who wins? How to reset/resync state? • JSON? Protobuf? Client
 (IntelliJ) Server
 (ReSharper)
  • 24. MVVM • Only send data required for UI components • Lightweight View Model data View
 (IntelliJ) Model
 (ReSharper) View
 Model
  • 26. Shared View Model • Single view of state of entire IDE
 Shared between front end and back end
 Keep in sync. Only need to update changed fields • Becomes declarative
 No more boilerplate messages, just update View Model • Reactive/observable. Composable
 Subscribe for changes • Two way
 Client and server can both contribute to View Model
 E.g. button click/refactoring results • Tightly coupled? 🤔
  • 27. Conflict resolution • The client is always right • Each value has a version • Version increments only when client changes value • If server changes value, no version update • Only accept change with same or newer version
  • 29. Wire protocol • Becomes trivial - no messages, just deltas
 Don’t change the protocol, just extend model • Supports batching • Serialisation by code generation via DSL • Binary wire protocol, with logging • Sockets
  • 30. Rider Framework • Two libraries, C# and Kotlin
 Provides primitives and handles communication • Kotlin based DSL to describe View Model • Generates real code - C# and Kotlin
 Interfaces, implementation and serialisation • Business logic subscribes to and manipulates “real model”
 Magic happens
  • 31. View Model building blocks • Lifetime • Signals (events) • Properties (observable value) • Maps (observable collections) • Fields (immutable) • Call (async RPC) • string • int • enum • classdef (node) • structdef (data)
  • 32. Lifetime class Lifetime { static Lifetime Eternal; void Add(Action action); } class LifetimeDef { ctor(Lifetime parent); Lifetime Lifetime; void Terminate(); } Dual of IDisposable
  • 33. Signal // Produce event interface ISource<T> { void Fire(T value); } // Subscribe to event interface ISink<T> { void Advise(Lifetime l, Action<T> handler); } // Composable event interface ISignal<T> : ISource<T>, ISink<T> { }
  • 34. Properties // Subscribe to event interface ISink<T> { void Advise(Lifetime l, Action<T> handler); } // Observable property interface IProperty<T> : ISink<T> { T Value { get; set; } void View(Lifetime l, Action<Lifetime, T> action); } Stateful signal
  • 35. Maps class MapEvent<K,V> { enum Kind { Add, Remove } Kind kind; K key; V value; } // Observable collection interface IViewableMap<K,V> : IDictionary<K,V>, ISink<MapEvent<K,V >> { void View(Lifetime l, Action<Lifetime, K, V> action); }
  • 36. Kotlin DSL fun classdef ( name : String, init : ClassdefNode.() -> Unit ) classdef ( “Foo”, { myClassdef.map(…) } ) classdef ( “Foo”, { map(…) } )
  • 37. Kotlin DSL fun classdef ( name : String, init : ClassdefNode.() -> Unit ) classdef ( “Foo”, { lambda_expression } ) classdef (“Foo”) { lambda_expression }
  • 38. object Solution { init { map(“editors”, string, classdef(“Editor”) { list(“document”, char) property(“caret”, int) map(“highlighters”, Range, Highlighter) property(“completion”, Completion.nullable) }) voidSource(“build”) } val Range = classdef(“Range”) { field(“start”, int) field(“length”, int) } val Highlighter = classdef(“Highlighter”) { … } }
  • 39. Challenges • Rider’s Project Model very different to IntelliJ
 Replace Project view with Solution Explorer
 IntelliJ uses “project” where we expect “solution” • What about duplicate language implementations?
 E.g. JavaScript - WebStorm or ReSharper?
 C++ CLion or ReSharper? • Plugins are more complex
 Front end and back end • ReSharper out of process with Visual Studio? 🙊