How do I update Clojure dependencies when working with nrepl.el? - emacs

As I understand it, when I do nrepl-jack-in a REPL is loaded along with all the dependencies defined in project.clj. If I then update project.clj to add a new dependency, do I need to kill the server and re-run nrepl-jack-in or is there way to update the dependencies in the current REPL?

Update: Maybe there is some hope,
See https://github.com/cemerick/pomegranate
Previously:
The short answer is yes - you do have to restart the JVM process.
I am aware of no good way to update dependencies in a live repl. Leiningen (called by nrepl-jack-in) will manage dependencies and set up the classpath only upon restarting. Trying to do something dynamic and clever is horribly fragile.
The struck out text below is factually true but upon a moment's reflection seemed such bad advice I have marked it up as such...
If you have a local dependency (e.g. jar file) you might use the long-time deprecated function add-classpath at the repl. But you will be entering the dragon infested swamp of java classloaders.

Restarting the REPL seems to be the simplest way. This can be done
with:
M-x cider-restart
That also appears to accomplish a lein deps. So the whole process
of adding a new dependency simply involves adding the require to
your project.clj and then invoking cider-restart.
Another (very convenient) way is to use
clj-refactor.
Adding the artifact (C-c m a p or cljr-add-project-dependency)
will prompt for the version you want, automatically put the new
dependency into your project.clj file, and reload your session.

Before pomegranate existed, I wrote my own library to dynamically load dependencies.
https://github.com/bmillare/dj
After the release of lein2 and how it under the covers can use pomegrante, I rewrote dj to use this underneath. So, even if you don't use 'dj', it might be a useful as a reference to see what its doing.

Related

Is there "any" possible way to Sync a local Scala library with our current project in order to have some sort of "hot reloading" of it?

I've been creating some projects in Scala, and there might be already several components that I constantly use , reuse or implement in different ways, I want to start putting all that stuff in some sort of a library but the problem is that I really want to have the chance to check its implementation while working, like the nice "Hot reloading" that the revolver plugin brings whenever we require to see the changes of our code in the console
For now its clear that whenever I want to publish something setup my local build.sbt file and publish it
sbt publishLocal
And then bring them as
"eu.myproject" %% "my-lib" % "1.0.0"
But I really would appreciate a way to work with this libraries with some real time sync in order to see the changes without having to publish them for each change
UPDATE
So thanks to Matthias Berndt I manage to update a project , with some nice hot reload still with revolver by configuring the sbt file as
lazy val root = Project ....
.dependsOn(
ProjectRef(file("/HOME/my-lib"), "my-lib"))
I still will research a nice pattern to bring some more local and published libraries in order to have them in dev and prod
You can use a ProjectRef to add the library as a subproject to the build system of the program that uses the library.
Check out this question: How do you use `ProjectRef` to reference a local project in sbt 1.x?
This blog post should also be helpful:
https://eed3si9n.com/hot-source-dependencies-using-sbt-sriracha

A hard way to get rid of everything generated by sbt

An easy way to get rid of *everything* generated by SBT? asks for an easy way to clean up all files generated from sbt, and didn't find one. I'll ask for a hard one. How do I get a make cleanall with sbt?
UPDATE: For a definition of everything, you have to know why you ever need to clean all. There are two common reasons:
To distribute something: You need to confirm that someone can take a fresh machine, download your code, and build it without problem. (Or, someone can't, and you want to debug).
When something has gone horribly wrong. Some funny version of some jar somewhere is breaking something somehow. Sometimes it's easiest to just start fresh, rather than try to debug... (See Jim Gray's Why Computers Stop)
Here are the usual suspects of things you need to clean:
~/.sbt/boot - Safe cache of sbt itself to avoid disappearing JAR oddiites
~/.sbt/**/target - Compiled global plugin/build definitions.
~/.ivy2/cache - Ivy cache of resolved dependencies
~/.ivy2/local - publishLocal files
<cwd>/project/**/target - Compiled build/plugin definitioins
<cwd>/**/target - Artifacts from building your project, including compiler caches, classfiles, etc.
sbt is unable to provide a "clean everything" task directly, because deleting the JARs/classes sbt is actively using to run your build leads to super odd and evil behavior. But you could write a simple BASH script which can accomplish this if desired.

Scala import not working - object <name> is not a member of package, sbt preppends current package namespace in imports

I have an issue when trying to import in scala. The object Database exists under com.me.project.database but when I try to import it:
import com.me.project.database.Database
I get the error:
object Database is not a member of package com.me.project.controllers.com.me.project.database
Any ideas what the problem is?
Edit:
It is worth mentioning that the import is in the file Application.scala under the package com.me.project.controllers, I can't figure out why it would append the import to the current package though, weird...
Edit 2:
So using:
import _root_.com.me.project.database.Database
Does work as mentioned below. But should it work without the _root_? The comments so far seem to indicate that it should.
Answer:
So it turns out that I just needed to clean the project for the import to work properly, using both:
import _root_.com.me.project.database.Database
import com.me.project.database.Database
are valid solutions. Eclipse had just gotten confused.
imports can be relative. Is that the only import you have? be careful with other imports like
import com.me
ultimately, this should fix it, then you can try to find more about it:
import _root_.com.me.project.database.Database
In my case I also needed to check that object which is not found as a member of package is compiled successfully.
I realize this question already has an accepted answer, but since I experienced the same problem but with a different cause I figured I'd add an answer.
I had a bunch of interdependent projects which suddenly needed a root import in order to compile. It turned out that I had duplicated the package declaration in a single file. This caused some kind of chain reaction and made it very hard to find the source of the problem.
In summary I had
package foo.bar
package foo.bar
on the top of the file instead of just
package foo.bar
Hope this saves someone some really tedious error hunting.
In my case I had to run sbt clean.
I had faced similar issue where IntelliJ showed error on importing one file from the same project.
What did not resolve the issue in my case:
adding _root_ in import statement
sbt clean
restarting machine
What actually resolved the issue:
main menu => select File => click on Invalidate Caches / Restart => pop-up dailog => click on invalidate the caches and restart.
I was using IDEA (2019.2.2 Ultimate Edition) on macOs mojave 10.14.6
Java -> Scala conversion without cleaning
Don't forget to clean if you convert some file in a project from Java to Scala. I had a continuous integration build running where I couldn't get things to work, even though the build was working locally, after I had converted a Java class into a Scala object. Solution: add 'clean' to the build procedure on the CI server. The name of the generated .class file in Scala is slightly different than for a Java class, I believe, so this is very likely what was causing the issue.
If you are using gradle as your build tool, then ensure that jar task is not disabled.
I had multiple modules in my project, where one module was dependent on a few other modules. However, I had disabled jar task in build.gradle:
jar {
enabled = false
}
That caused it to fail to resolve classes in the dependent modules and fail with the above error.
I will share my story, just in case it may help someone.
Scenario: intellij compilation succeeds, but gradle build fails on import com.foo.Bar, where Bar is a scala class.
TLDR reason: Bar was located under src/main/java/... as opposed to src/main/scala/...
Actual reason: Bar was not being compiled by compileScala gradle task (from gradle scala plugin) because it looks for scala sources only under src/<sourceSet>/scala.
From docs.gradle.org:
All the Scala source directories can contain Scala and Java code. The
Java source directories may only contain Java source code.
Hope this helps
I had a similar problem but none of the solutions here worked for me. What did work however was a simple restart of my machine.
Perhaps it was something with my Intellij but after a quick restart, everything seems to be working fine.
I had a similar situation, which was failing in both IntelliJ and maven on the command line. I went to apply the suggested temp fix (adding _root_) but intellij was glitching so bad that wasn't even possible.
Eventually I noticed that I had mis-created a package so that it repeated the whole path of the package. That meant that the directory my class was in had a subfolder called "com", and the start of my file looked like:
package com.mycompany.mydept.myproject.myfunctionality.sub1
import com.holdenkarau.spark.testing.DataFrameSuiteBase
where I had another package called
com.mycompany.mydept.myproject.myfunctionality.sub1.com.mycompany.mydept.myproject.myfunctionality.sub2
And the compiler was looking for "holdenkarau" under com.mycompany.mydept.myproject.myfunctionality.com and failing.
I had this issue while using Intellij and the built-in sbt shell (precisely, I was trying to run the command console, which invokes a compiler check of the code).
In my case, after trying the other suggested solutions on this thread, I found that I could restart the sbt shell and it would go away. There's a button on the left-hand side of a looped green arrow and a small grey square which does this in one click (obviously, this is subject to Jet Brains not changing the design of the IDE!!!).
I hope this helps some people get past this issue quickly.
In my case, In Intellij, Just renaming the package file to something else >> see if it updates the import statements >> run the code >> then renaming back to the original name worked.

Convenient way to run eclipse plugin

I have recently started developing an Eclipse plugin (which is basic stuff for now) and I am struggling with "default" way to run Eclipse plugin ("Run as Eclipse application").
The Eclipse is starting another instance with my plugin already installed in it (this is default behaviour).
The problem is that when I want to re-run my plugin project and I press "run" button again (or Ctrl + F11) (and the another Eclipse instance still running) I get following message:
"Could not launch the application because the associated workspace is currently in use by another Eclipse application".
The error makes sense, and when I close "testing" Eclipse instance I am able to run my plugin again.
The question is - "is it normal routine for plugin development?". Maybe I am missing something, e.g. special arguments for Eclipse?
This seems all pretty normal. The error message is since the run configuration is specifing a workspace and when you start a second instance using the same workspace it is locked and considered in use.
What I usually do when testing a plugin is to create a run configuration (click "Run...") where I disable all the plugins I wont need when testing. This makes sure that the test starts up a couple of seconds quicker. Make sure you save that run configuration as a *.launch file aswell, that makes it quicker to test the next time. Or it can be used to share the configuration.
There's a lot you can configure in the run configuration, such as eclipse arguments, vm argument, if you want environment variables set, etc. So be sure to experiment a little.
In your run configuration. Main tab->Workspace Data ->Location text box add this:
${workspace_loc}/../runtime-EclipseApplication${current_date:yyyyMMdd_HHmmss}
Note the suffix ${current_date:yyyyMMdd_HHmmss} by this every time you launch your application new workspace will be created. So you will not get any error message saying workspace is locked.
But be careful as the folder .metadata will be different for different instances as their work-spaces are different. Thus preferences stored/retrieved by different instances are NOT in sync.
You are probably missing one important point: Eclipse supports the Java hot code replacement. Therefore in many cases you can modify your Java code while your application Eclipse instance is running, save the code and continue without restarting.
If hot code replacement is not possible, Eclipse will tell you, so you always know whether the editing changes are applied to the running instance.
This works best with more recent versions of the JVM, so consider upgrading to the latest Java 7 version, even if you write code to be compliant with Java 1.5 or 6.

how to auto-reload changed scala classes into SBT REPL

I am new to Scala and to using emacs + ensime + sbt setup for my Scala development.
This setup is quite nice and light, but there is one thing which drives me nuts - inability to auto-compile / reload changes into Scala console started from sbt.
I use REPL a lot and would like to be able to start REPL from sbt with console command and test my changes to scala classes from REPL without having to close it and reload every time I make a change.
I come from Erlang environment and this way of development is easy with Erlang but seems to be difficult with SBT. I have the JRebel plug-in installed but it doesn't seem to be working for the situation I described.
Has anybody been able to make something similar work and would be willing to share the configuration steps?
Much appreciated in advance.
There are two things possible in sbt:
Causing automatic recompilation of the project sources triggered by a file change by prefixing a command with ~ (tilde). The console, or console-quick, or console-project commands can be prefixed, too, but you have to exit REPL to make the recompilation happen (just hit Ctrl+D and wait.)
Causing automatic execution of REPL commands just after firing the console. They can be defined as properties (e.g. in build.sbt):
initialCommands in console := """
import some.library._
def someFun = println("Hello")
"""
It's not necessary to define the property separately in consoleQuick because it defaults to the one defined in console, but if you would like to use the console-project command you have to define it separately.
On a final note: remember to leave empty line between every property in an *.sbt file. They're necessary to parse the properties correctly. In the example above there are no blank lines in between so it means that everything goes into the initialCommands property (and that's what we want.)