vscode-code-runner icon indicating copy to clipboard operation
vscode-code-runner copied to clipboard

Java Package And Class File Removal

Open rockyzhang24 opened this issue 7 years ago • 12 comments

Hey dear developer,

  1. 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?

  2. 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.

rockyzhang24 avatar May 30 '17 08:05 rockyzhang24

For 1, I will consider about it. For 2, duplicated with #84

formulahendry avatar Jun 01 '17 02:06 formulahendry

@formulahendry 谢谢!!

rockyzhang24 avatar Jun 01 '17 02:06 rockyzhang24

@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 "). It seems that the class path is not included in the run statement that is executed, from looking at the output as well as the executormap configuration. Is there a way to add the class path to the executormap configuration for java to successfully run the the code with code-runner? Any solution ideas would be appreciated.

jheathj avatar Jun 14 '17 15:06 jheathj

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?

sake92 avatar Sep 18 '17 15:09 sake92

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 avatar Sep 19 '17 11:09 formulahendry

@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... 😅

sake92 avatar Sep 22 '17 18:09 sake92

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 always src/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 using javac/java

formulahendry avatar Sep 23 '17 06:09 formulahendry

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 avatar Nov 27 '18 10:11 chadirino

@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

ileadall42 avatar Dec 30 '18 15:12 ileadall42

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

StoneRen avatar Feb 13 '19 06:02 StoneRen

So, now do we have any easy solutions to this problem?

Clelo-key avatar Jun 05 '22 14:06 Clelo-key

Any simple solution yet?

imakhlaq avatar Aug 21 '22 22:08 imakhlaq