INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type...

53
INTEGRATING IDE INTEGRATING IDEs WITH DOTTY WITH DOTTY - EPFL Guillaume Martres 1

Transcript of INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type...

Page 1: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

INTEGRATING IDEINTEGRATING IDEssWITH DOTTYWITH DOTTY

- EPFLGuillaume Martres

1

Page 2: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

WHAT IS DOTTY?WHAT IS DOTTY?Research compiler that will become Scala 3Type system internals redesigned, inspired by DOT,but externally very similarMore info:

Recent blog posts on dotty.epfl.ch

scala-lang.org

2

Page 3: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

A CHANCE TO REDESIGNA CHANCE TO REDESIGNCOMPONENTSCOMPONENTS

Improved incremental compilation (avoidundercompilation)Better pattern matching checks (

)algorithm now

reused in Swi�!

3

Page 4: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

TOOLINGTOOLINGA good developer experience requires good tools:

A REPL (with syntax highlighting!)Dottydoc (used to generate

)IDE supportdotty.epfl.ch/docs

4

Page 5: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

STATE OF THE ARTSTATE OF THE ARTBased on the

Scala-IDEENSIME

Reimplementation of the Scalatypechecker

Scala plugin for IntelliJ IDEA

Scala Presentation Compiler

5

Page 6: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

STATE OF THE ARTSTATE OF THE ARTBased on the (3KLOC)

Scala-IDE (66 KLOC)ENSIME (server: 15 KLOC, emacs client: 10KLOC)

Reimplementation of the Scala typecheckerScala plugin for IntelliJ IDEA (230 KLOC)

Scala Presentation Compiler

6

Page 7: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

DESIGN PRINCIPLESDESIGN PRINCIPLES1. Code reuse2. Editor-agnosticity3. Easy to use (and to

install!)

7

Page 8: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

DESIGN PRINCIPLESDESIGN PRINCIPLES1. Code reuse2. 3.

Editor-agnosticityEasy to use (and toinstall!)

8

Page 9: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

QUERYING THE COMPILERQUERYING THE COMPILER

Each phase progressively simplify trees until theycan be emitted as JVM bytecode

9

Page 10: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

QUERYING THE COMPILERQUERYING THE COMPILER

Each phase progressively simplify trees until theycan be emitted as JVM bytecode

10

Page 11: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

SOURCE CODESOURCE CODE

Cursor position = 🚩Query: jump todefinition

final val elem = 1

val foo = elem🚩 + 1

11

Page 12: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

TREE AFTER TREE AFTER TyperTyper

Every tree node has a type and apositionQuery can be answered

final val elem: 1 = 1

val foo: Int = elem + 1

12

Page 13: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

TREE AFTER TREE AFTER FirstTransformFirstTransform

Information lost by constantfoldingImpossible to answer query

final val elem: 1 = 1

val foo: Int = 2

13

Page 14: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

QUERYING THE COMPILERQUERYING THE COMPILERStore trees before FirstTransformRespond to IDE queries by traversing treesWhat about code that has already beencompiled?

14

Page 15: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

PICKLINGPICKLING

In Scala 2: store methods signatures (for separatecompilation)In Dotty: store full trees

15

Page 16: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

TASTY: TYPED ASTTASTY: TYPED ASTSERIALIZATION FORMATSERIALIZATION FORMAT

Original motivation: solve the

Always use JVM bytecode: breaks when compilerencoding changesAlways recompile source code: breaks when thetypechecker changes

Can also be used to provide interactive features:deserialize and query trees

binary compatibilityproblem

16

Page 17: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

INTERACTIVE APISINTERACTIVE APISConvenience methods for tree traversals, compilerlifecycle managementUsed both in the IDE and the REPL (e.g., forcompletions)In the future: interruption handling, partialtypechecking, ...Less then 1 KLOC

17

Page 18: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

DESIGN PRINCIPLESDESIGN PRINCIPLES1. 2. Editor-agnosticity3.

Code reuse

Easy to use (and toinstall!)

18

Page 19: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

THE IDE PORTABILITY PROBLEMTHE IDE PORTABILITY PROBLEMGetting m IDEs to support n programming languagesrequires n*m IDE plugins.

19

Page 20: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

THE LANGUAGE SERVERTHE LANGUAGE SERVERPROTOCOLPROTOCOL

20

Page 21: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

BASICS OF THE LSPBASICS OF THE LSPFirst implemented in Visual Studio CodeJSON-RPCIDE notifies the language server about user actionsLS maintains internal representation of codeLS notify IDE about warnings/errorsIDE can send requests usually triggered by useractionsAsynchronous, cancelable

21

Page 22: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

IMPLEMENTING THE DOTTYIMPLEMENTING THE DOTTYLANGUAGE SERVERLANGUAGE SERVER

Low-level message handling done by

Relies on interactive APIs0.5 KLOC

EclipseLSP4J

22

Page 23: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

override def definition(params: TextDocumentPositionParams) =

}

23

Page 24: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

override def definition(params: TextDocumentPositionParams) =

computeAsync { cancelToken =>

}

24

Page 25: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

override def definition(params: TextDocumentPositionParams) =

computeAsync { cancelToken =>

val uri = new URI(params.getTextDocument.getUri)

}

25

Page 26: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

override def definition(params: TextDocumentPositionParams) =

computeAsync { cancelToken =>

val uri = new URI(params.getTextDocument.getUri)

val driver = driverFor(uri)

}

26

Page 27: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

override def definition(params: TextDocumentPositionParams) =

computeAsync { cancelToken =>

val uri = new URI(params.getTextDocument.getUri)

val driver = driverFor(uri)

implicit val ctx = driver.currentCtx

}

27

Page 28: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

override def definition(params: TextDocumentPositionParams) =

computeAsync { cancelToken =>

val uri = new URI(params.getTextDocument.getUri)

val driver = driverFor(uri)

implicit val ctx = driver.currentCtx

val pos = sourcePosition(driver, uri, params.getPosition)

}

28

Page 29: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

override def definition(params: TextDocumentPositionParams) =

computeAsync { cancelToken =>

val uri = new URI(params.getTextDocument.getUri)

val driver = driverFor(uri)

implicit val ctx = driver.currentCtx

val pos = sourcePosition(driver, uri, params.getPosition)

val uriTrees = driver.openedTrees(uri)

}

29

Page 30: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

override def definition(params: TextDocumentPositionParams) =

computeAsync { cancelToken =>

val uri = new URI(params.getTextDocument.getUri)

val driver = driverFor(uri)

implicit val ctx = driver.currentCtx

val pos = sourcePosition(driver, uri, params.getPosition)

val uriTrees = driver.openedTrees(uri)

val sym = Interactive.enclosingSourceSymbol(uriTrees, pos)

}

30

Page 31: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

override def definition(params: TextDocumentPositionParams) =

computeAsync { cancelToken =>

val uri = new URI(params.getTextDocument.getUri)

val driver = driverFor(uri)

implicit val ctx = driver.currentCtx

val pos = sourcePosition(driver, uri, params.getPosition)

val uriTrees = driver.openedTrees(uri)

val sym = Interactive.enclosingSourceSymbol(uriTrees, pos)

val classTree =

SourceTree.fromSymbol(sym.topLevelClass.asClass).toList

}

31

Page 32: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

override def definition(params: TextDocumentPositionParams) =

computeAsync { cancelToken =>

val uri = new URI(params.getTextDocument.getUri)

val driver = driverFor(uri)

implicit val ctx = driver.currentCtx

val pos = sourcePosition(driver, uri, params.getPosition)

val uriTrees = driver.openedTrees(uri)

val sym = Interactive.enclosingSourceSymbol(uriTrees, pos)

val classTree =

SourceTree.fromSymbol(sym.topLevelClass.asClass).toList

val defTree = Interactive.definition(classTree, sym)

}

32

Page 33: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

override def definition(params: TextDocumentPositionParams) =

computeAsync { cancelToken =>

val uri = new URI(params.getTextDocument.getUri)

val driver = driverFor(uri)

implicit val ctx = driver.currentCtx

val pos = sourcePosition(driver, uri, params.getPosition)

val uriTrees = driver.openedTrees(uri)

val sym = Interactive.enclosingSourceSymbol(uriTrees, pos)

val classTree =

SourceTree.fromSymbol(sym.topLevelClass.asClass).toList

val defTree = Interactive.definition(classTree, sym)

defTree.map(d => location(d.namePos)).asJava

}

33

Page 34: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

DESIGN PRINCIPLESDESIGN PRINCIPLES1. 2. 3. Easy to use (and to

install!)

Code reuseEditor-agnosticity

34

Page 35: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

SBT INTEGRATIONSBT INTEGRATIONAnalyze the build to find DottyprojectsCompile these projectsGenerate configuration filesInstall the Dotty VSCode extensionLaunch VSCode

35

Page 36: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

CONFIGURATION FILESCONFIGURATION FILES.dotty-ide-artifact, used by the IDEextension to launch the Dotty Language Server:

ch.epfl.lamp:dotty-language-server_0.8:0.8.0-RC1

36

Page 37: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

CONFIGURATION FILESCONFIGURATION FILES.dotty-ide.json, used by the DLS to launchcompiler instances:[

{

"id" : "root/compile",

"compilerVersion" : "0.8.0-RC1",

"compilerArguments" : [ ],

"sourceDirectories" : [ "src/main/scala" ],

"dependencyClasspath" : [ ... ],

"classDirectory" : "target/scala-0.8/classes"

},

{

"id" : "root/test",

...

},

...

]

37

Page 38: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

BUILD SERVER PROTOCOLBUILD SERVER PROTOCOLInstead of making plugins for build tools to extractinformation, ask them!We also need a discovery protocol: "How do I start abuild server for this project?"

38

Page 39: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

DESIGN PRINCIPLES, REVISITEDDESIGN PRINCIPLES, REVISITED1. Code reuse

Compiler APIs for interactive usage2. Editor-agnosticity

Implemented the LSP3. Easy to use (and to install!)

One command (but we can dobetter!)

39

Page 40: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

GOING FURTHER: DEBUGGERGOING FURTHER: DEBUGGERSUPPORTSUPPORT

Based on the Most features "just work"(Not actually merged in Dottyyet)Challenge: expressionevaluation

Java Debug Server

40

Page 41: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

EXPRESSION EVALUATIONEXPRESSION EVALUATIONclass Hello {

def foo(implicit y: Context): String = { /*...*/ }

def bar(implicit y: Context) = {

/*...*/

}

}

41

Page 42: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

EXPRESSION EVALUATIONEXPRESSION EVALUATIONclass Hello {

def foo(implicit y: Context): String = { /*...*/ }

def bar(implicit y: Context) = {

🚩 /*...*/

}

}

42

Page 43: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

EXPRESSION EVALUATIONEXPRESSION EVALUATIONclass Hello {

def foo(implicit y: Context): String = { /*...*/ }

def bar(implicit y: Context) = {

🚩 foo /*...*/

}

}

43

Page 44: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

RUN THE COMPILER PIPELINERUN THE COMPILER PIPELINEclass Hello {

def foo(y: Context): String = { /*...*/ }

def bar(y: Context) = {

🚩 this.foo(y) /*...*/

}

}

44

Page 45: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

EXTRACT TO A STATIC METHODEXTRACT TO A STATIC METHODobject Global {

def liftedExpr($this: Hello, y: Context) =

$this.foo(y)

}

45

Page 46: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

EXTRACT TO A STATIC METHODEXTRACT TO A STATIC METHODobject Global {

def liftedExpr($this: Hello, y: Context) =

$this.foo(y)

def exec(self: Object, localVariables: Map[String, Object]) =

liftedExpr(

self.asInstanceOf[Hello],

localVariables("y").asInstanceOf[Context]

)

}

46

Page 47: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

ON THE DEBUGGING VMON THE DEBUGGING VMCompile Global to a classfileLoad it in the debugged VMCall Global.exec with the rightarguments

47

Page 48: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

ON THE DEBUGGED VMON THE DEBUGGED VMIn the standardlibrarypackage dotty.runtime

object DebugEval {

def eval(classpath: String,

self: Object,

localVariables: Map[String, Object]): Any = {

val cl = new URLClassLoader(Array(new URL("file://" + classpath)

val cls = cl.loadClass("Global")

val instance = cls.newInstance

val exec = cls.getMethod("exec")

exec.invoke(instance, self, names, args)

}

}

48

Page 49: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

ON THE DEBUGGING VMON THE DEBUGGING VMWe want to remotely execute:

val classpath = <classpath for the compiled Global class>

val self = <this in the stackframe>

val localVariables = <map of local variables in the stackframe>

dotty.runtime.DebugEval(classpath, self, localVariables)

49

Page 50: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

ON THE DEBUGGING VMON THE DEBUGGING VMWe use the Java Debugging Interface APIs:

val vars = stackFrame.visibleVariables

val mapCls =

vm.classesByName("java.util.Map")

.get(0).asInstanceOf[ClassType]

val localVariablesRef = mapCls.newInstance()

// Skipped: store `vars` into `localVariablesRef`

val debugCls =

vm.classesByName("dotty.runtime.DebugEval")

.get(0).asInstanceOf[ClassType]

val eval =

debugCls.methodsByName("eval").get(0)

debugCls.invokeMethod(

thread, eval,

List(vm.mirrorOf(classpath), stackFrame.thisObject,

localVariablesRef)

)

50

Page 51: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

FUTURE WORKFUTURE WORKOptimizationsMore features

Documentation on hoverBetter build tool integration (Build ServerProtocol!)

51

Page 52: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

CONCLUSIONCONCLUSIONDesign your compiler with interactivity in mindDesign your build tool with interactivity in mindInteractivity should go beyond what IDEs and REPLscurrently offer

Type Driven Development with Idris

52

Page 53: INTEGRATING IDE s WITH DOTTY · W H AT I S DOT TY? Research compiler that will become Scala 3 Type system internals redesigned, inspir ed by DOT, but externally v er y similar More

QUESTIONS ?QUESTIONS ?More info: Come chat with us:

Contributors welcome!

dotty.epfl.ch

gitter.im/lampepfl/dotty

53