publicclassCommandLineTool{publicstaticvoidmain(string[]args)throwsException{finalstringprojectPath=YOUR_PATH/* (1) Get project path, for example, from args or system properties */;finalEnvironmentConfigconfig=EnvironmentConfig.emptyConfig().withDefaultPlugins().withBootstrapLibraries();config.addPlugin("http-support","jetbrains.mps.ide.httpsupport");finalIdeaEnvironmentenv=newIdeaEnvironment(config);env.init();finalProjectproject=env.openProject(newFile(projectPath));Throwablethrown=null;try{doSomething();// 2}catch(Exceptione){thrown=e;}finally{env.dispose();}if(thrown!=null){System.err.println("ERROR:");thrown.printStackTrace();System.exit(1);}else{// You need `System.exit` even in a successful case to stop threads that MPS plugins may be leaving behind.System.exit(0);}}}
What can you do with the project (at point 2)? Here is how you invoke a static method foo() on class Bar in module Baz:
Why are all the reflection tricks needed, and why not call the class directly instead? The answer is that when MPS is initialized and a project opens, it sets up classloaders and puts any dependencies module Baz might have on the classpath so that you don't have to specify them ourselves.
We still need to have the initial set of JARs on the classpath to run our class and start MPS. Here is how you would run our tool from Gradle:
taskrunCommandLineTool(type:JavaExec){main='CommandLineTool'classpathfile('solutions/commandline/classes_gen')// Location of CommandLineTool.classclasspathfileTree("$mps_home/lib")// $mps_home points to the MPS installation}
You can also add MPS to the Gradle dependencies block: