vscode-code-runner
vscode-code-runner copied to clipboard
Java Package And Class File Removal
Hey dear developer,
-
If the java file has a package statement at the first line or import other my own packages, Code Runner cannot compile the files. Could you please improve it to support this?
-
Could you please improve this fabulous extension to make it be able to remove the .class files after compiling and running??
Thank you so much.
For 1, I will consider about it. For 2, duplicated with #84
@formulahendry 谢谢!!
@formulahendry
I am testing out a Java maven project in VSCode, running it with code-runner. As mentioned above, it seems that with a package declaration in the Java file, code-runner fails to run (Error I receive: "Error: Could not find or load main class
First, a quick intro to my solution. A common practice in Java projects (I think Maven first started this) is to put Java sources in src/main/java
.
If so, it's easy to determine class' fqn (fully qualified name), e.g.
package ba.sake
public class Blah {}
must be in folder src/main/java/ba/sake
in a file called Blah.java
.
The solution would be to make a method getJavaClassFullyQualifiedName()
and a corresponding property called javaClassFullyQualifiedName
.
Then, in user's setting we could say:
"code-runner.executorMap": {
"java": "cd $workspaceRoot\\src\\main\\java && javac -cp . $fullFileName && java -cp . $javaClassFullyQualifiedName",
}
I tried this and it works. One downside is that you have to specify src/main/java
...
But, some users, especially beginners, use only one file/class just to try out Java, so it should be configurable.
If there are no issues with this, I'll make a pull request. Anyone?
Hi @sake92 , thanks for your passion on this feature! But I am afraid the change will break current users who do not use package ba.sake
. Also, take care file path in Linux and macOS. We need to consider backwards compatibility of this feature.
@formulahendry I don't see how this would break current users. We could leave the settings as they are now and just add javaClassFullyQualifiedName
property.
A better solution could be to add another Java-specific property, like javaBaseFolder
to specify that it is src/main/java
for example. Then we could do this:
"java": "cd $javaBaseFolder && javac -cp . $fullFileName && java -cp . $javaClassFullyQualifiedName"
where javaClassFullyQualifiedName
would be computed based on javaBaseFolder
.
That would be the best, I think.
Another "issue" with Java is that you need to add classes and necessary JARs to classpath (-cp setting).
But that is user-specific and there is no "standard" way...
That could be yet another property... 😅
Thanks @sake92 . If we are not changing current executorMap, that would be OK. I am not quite familiar with Java, so I may have some questions:
- For
javaBaseFolder
, is it just$workspaceRoot
+src/main/java
? And is it alwayssrc/main/java
? - For
need to add classes and necessary JARs to classpath
, I am not sure it is better to use Maven/Gradle instead of usingjavac
/java
My Current Setting
"java": "echo off\nset fileDir=$dir\nset fileDir=%fileDir:\"=%\njavac -d bin -cp bin %fileDir%*.java\nset class=%fileDir%$fileNameWithoutExt\nset class=%class:$workspaceRoot\\src\\=%\nset class=%class:\\=.%\njava -cp bin %class%\necho on"
In the command line, it would look like this (I kept code-runner variables for privacy):
echo off
set fileDir=$dir // set file directory variable
set fileDir=%fileDir:"=% // remove quotes from directory path
javac -d bin -cp bin %fileDir%*.java // compile all Java files in file directory
set class=%fileDir%$fileNameWithoutExt // set fully qualified class name variable
set class=%class:$workspaceRoot\\src\\=% // convert to path relative to sourcepath
set class=%class:\=.% // switch out slashes for periods
java -cp bin %class% // launch the Java file
echo on
I created fileDir
because the $dir
variable contains quotes. It might be easier to let users add quotes, if needed -- might relate to issue #217. I compiled all files in the file directory because sometimes I use packages with inter-dependent classes. bin
is the name of my classpath folder. Also, I switched out %%
for \n
because otherwirse I get errors -- not sure why -- and it also looks cleaner.
My Ideal Realistic Setting
Basically, I would merely like to remove the two (kinda of unecessary) commands.
echo off
javac -d bin -cp bin $dir*.java // compile all Java files in file directory
set class=$dir$fileNameWithoutExt // set fully qualified class name variable
set class=%class:$workspaceRoot\\src\\=% // convert to path relative to sourcepath
set class=%class:\=.% // switch out slashes for periods
java -cp bin %class% // launch the Java file
echo on
The Ideal Setting
This obviously would be the most ideal setting for Java coders.
echo off
javac -d bin -cp bin $dir*.java // compile all Java files in file directory
java -cp bin $fullyQualifiedName // launch the Java file
echo on
Conclusion
All-in-all, I think most users would be content with a setting similar to that of my ideal realistic one. As a suggestion, it might be worth adding vscode-like variables such as ${workspaceFolder}
and ${relativeFile}
, in case anyone needs them. As for the fully qualified class name variable, I'm not sure if it is worth creating a specific variable just for Java. It would be pretty nice, though.
@chadirino Thanks for your advice and my setting is like follow @sake92 this may help.
it is base on mac os.If in windows it may need to change / -> //
"java": "src=src && outDir=bin && source=$dirWithoutTrailingSlash && dest=${source/$src/$outDir} && mkdir -p $dest && cd $dir && javac -d $workspaceRoot/$outDir $fileName && packagePath=${dest##*$outDir/} && java -cp $workspaceRoot/$outDir $packagePath.$fileNameWithoutExt"
Detail
src=src && // set the src name of your project
outDir=bin && // if use the java view create java project is bin ,if maven project maybe target.
source=$dirWithoutTrailingSlash && // the source
dest=${source/$src/$outDir} && // replace the src to output (the package will contain)
mkdir -p $dest && //mkdir the dir if not exist
cd $dir && //change the dir
javac -d $workspaceRoot/$outDir $fileName && // javac and specify the dir
pacakageName=${dest##*$outDir/} && // delete the prefix
java -cp $workspaceRoot/$outDir $pacakageName.$fileNameWithoutExt // specify the classpath and run like org.apache.App
javac -d $workspaceRoot/$outDir $fileName
=>
javac -d $workspaceRoot/$outDir -cp $workspaceRoot/src $fileName
add -cp $workspaceRoot/src
This way work good 👍
@chadirino Thanks for your advice and my setting is like follow @sake92 this may help.
it is base on mac os.If in windows it may need to change / -> //
"java": "src=src && outDir=bin && source=$dirWithoutTrailingSlash && dest=${source/$src/$outDir} && mkdir -p $dest && cd $dir && javac -d $workspaceRoot/$outDir $fileName && packagePath=${dest##*$outDir/} && java -cp $workspaceRoot/$outDir $packagePath.$fileNameWithoutExt"
Detail
src=src && // set the src name of your project outDir=bin && // if use the java view create java project is bin ,if maven project maybe target. source=$dirWithoutTrailingSlash && // the source dest=${source/$src/$outDir} && // replace the src to output (the package will contain) mkdir -p $dest && //mkdir the dir if not exist cd $dir && //change the dir javac -d $workspaceRoot/$outDir $fileName && // javac and specify the dir pacakageName=${dest##*$outDir/} && // delete the prefix java -cp $workspaceRoot/$outDir $pacakageName.$fileNameWithoutExt // specify the classpath and run like org.apache.App
So, now do we have any easy solutions to this problem?
Any simple solution yet?