Writing Java sourcecode in Emacs is a rather hard task. Emacs does not usually support the developer with lots of context awareness (friendly put…). What does the unsatisfied developer do when he is in need for functionality? He codes his own solution! So I have just started work on „Emacs Java Coding Extension (version 0.0.1)“. The project is admittedly in a very early phase. But there is an ambitious roadmap and some lines of code already available. Fresh from the scratch buffer where I tried it out:

(defvar mp:ac-classpath-cache nil)
 
(defun mp:ac-classpath-init ()
  (setq mp:ac-classpath-cache (mp:read-classes-from-jar)))
 
(defvar ac-source-classpath
  '((prefix . "^import \\(.*\\)")
    (init . mp:ac-classpath-init)
    (candidates . mp:ac-classpath-cache)))
 
(defun mp:read-classes-from-jar ()
  (with-temp-buffer
    (call-process "/usr/bin/unzip" nil t nil "-l" "/home/map/opt/jdk1.8.0_101/jre/lib/rt.jar")
    (goto-char (point-min))
    (let ((end 0)
          (result '())
          (classname ""))
      (while (search-forward ".class" nil t nil)
        (end-of-line)
        (setq end (point))
        (beginning-of-line)
        (goto-char (+ (point) 30))
        (setq classname (substring 
                         (replace-regexp-in-string "/" "."
                                                   (buffer-substring-no-properties (point) end))
                         0 -6))
        (setq result (cons classname result))
        (forward-line 1)
        (beginning-of-line))
      result)))

Put together correctly the code supplies a auto-complete source that knows about classes from the java rt.jar file (or any other jar file, or with some modifications several jar files).

Introduction

Jdee is a major-mode for Emacs that supports Java developers with many usefull functions. Some of which are

  • automatic completion of class fields and methods
  • browse JDK doc, using the browser of your choice
  • generates class and method skeletons automatically

It has been in a sort of sleeping-state until round about a year ago. Until then it appeared to be without major changes for long. Some time ago the project was moved to github and there seems to be something going on now. For example it looks like it’s getting some client-server touch since now there is jdee-server (which is written in java).

Installation

I have installed Jdee via emacs package system (elpa) which was easy (list-packages) and (use-package):

(use-package jdee)

This way .java files are immediatly opened in jdee-mode. After browsing through some java files and invoking random jdee menu entries I was told that jdee-server was missing. So I had to (customize-variable) jdee-serve-dir to tell jdee where jdee-server is located. I also had to take care that there is a jdee-server.jar file available. To achieve this have cloned jdee-server from github and „mvn package“-ed the file.

Customization

Customization in jdee is mainly done via (customize-group) jdee. I was running into a known issue when doing (customize-group) jdee. However I could work around by switching to (customize-variable) whenever customization via (customize-group) was not working.

Checkstyle

Since there are many functions available and I do not really enter that many java code in Emacs at the moment I picked one feature I was curious to to have a look at – „Checkstyle“. To get checkstyle working in jdee I had to „Get checkstyle“ first… Since „Checkstyle“ has rather a lot of dependencies I grabbed me the maven pom from checkstyle ( search.maven.org ) and asked maven to download all dependencies:

$ mvn dependency:download-dependencies

All dependencies must be configured in emacs as well (customize-variable) „jdee-checkstyle-classpath“. Which resulted for me in this (bit lengthy) entry in custom-set-variables:

'(jdee-checkstyle-classpath
(quote
("~/.emacs.d/jdee-server/checkstyle/lib/ant-1.9.7.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/ant-launcher-1.9.7.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/antlr-2.7.7.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/antlr4-runtime-4.5.3.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/checkstyle-6.19.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/commons-beanutils-1.9.2.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/commons-cli-1.3.1.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/commons-codec-1.6.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/commons-collections-3.2.2.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/commons-io-2.5.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/commons-logging-1.1.1.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/equalsverifier-2.1.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/guava-19.0.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/hamcrest-core-1.3.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/httpclient-4.3.6.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/httpcore-4.3.3.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/JavaEWAH-0.7.9.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/javassist-3.20.0-GA.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/jsch-0.1.53.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/junit-4.12.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/mockito-core-1.10.19.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/objenesis-2.1.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/org.eclipse.jgit-4.3.1.201605051710-r.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/org.jacoco.agent-0.7.6.201602180812-runtime.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/powermock-api-mockito-1.6.5.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/powermock-api-mockito-common-1.6.5.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/powermock-api-support-1.6.5.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/powermock-core-1.6.5.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/powermock-module-junit4-1.6.5.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/powermock-module-junit4-common-1.6.5.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/powermock-reflect-1.6.5.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/slf4j-api-1.7.2.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/slf4j-simple-1.7.21.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/system-rules-1.16.0.jar"
"~/.emacs.d/jdee-server/checkstyle/lib/tools-1.7.0.jar")))

To get this list I had a little line of shell-script working for me:

$ for file in *.jar ; do echo -n "\"$(pwd)/${file}\" " ; done

I copied the output into emacs customization-file and added parentheses (way quicker then manually entering all the file-names 🙂 ).
 

Style

Finally checkstyle needs a xml file that describes the style it is checking for. One called „Google’s Style“ can be obtained from the official checkstyle website. It must be told to jdee that this file should be used (customize-variable) „jdee-checkstyle-style“ and that should be it already. If now under Checkstyle is invoked for the current buffer (via JDEE-menu Checkstyle) a buffer opens in compilation mode and shows the checkstyle results (for me in german):

Emacs24 doing check style

Resume

Judging from my installation process (home-growing jdee-server, obtaining check-style) JDEE seems a bit un-integrated. Also it brings a lot of java-code into Emacs.
Also (install-package) „JDEE“ is not even half the rent. It’s in fact the top of the eisberg. There seems to be a bit  of work to do keep the package up to date once an update is necessary. However initially the hurdles have not been too high to get jdee-server and check-style ready to play with and finally the promised feature was working. So current resume: Thumbs up – „Hooray for JDEE“!