33import java .nio .file .Path ;
44import java .nio .file .Paths ;
55import java .util .ArrayList ;
6+ import javax .tools .FileObject ;
7+ import javax .tools .JavaFileManager ;
8+ import javax .tools .JavaFileObject ;
69
7- /** Settings that can be configured alongside the -Xplugin compiler option. */
10+ import com .sun .tools .javac .util .Context ;
11+
12+ import static javax .tools .StandardLocation .CLASS_OUTPUT ;
13+
14+ /**
15+ * Settings that can be configured alongside the -Xplugin compiler option.
16+ */
817public class SemanticdbJavacOptions {
918
10- /** The directory to place */
19+ /**
20+ * The directory to place META-INF and its .semanticdb files
21+ */
1122 public Path targetroot ;
1223
1324 public Path sourceroot ;
1425 public boolean includeText = false ;
1526 public boolean verboseEnabled = false ;
1627 public final ArrayList <String > errors ;
1728
29+ public static String stubClassName = "META-INF-stub" ;
30+
1831 public SemanticdbJavacOptions () {
1932 errors = new ArrayList <>();
2033 }
@@ -26,11 +39,20 @@ public static String missingRequiredDirectoryOption(String option) {
2639 option , option );
2740 }
2841
29- public static SemanticdbJavacOptions parse (String [] args ) {
42+ public static String JAVAC_CLASSES_DIR_ARG = "javac-classes-directory" ;
43+
44+ public static SemanticdbJavacOptions parse (String [] args , Context ctx ) {
3045 SemanticdbJavacOptions result = new SemanticdbJavacOptions ();
46+ boolean useJavacClassesDir = false ;
3147 for (String arg : args ) {
3248 if (arg .startsWith ("-targetroot:" )) {
33- result .targetroot = Paths .get (arg .substring ("-targetroot:" .length ()));
49+ String argValue = arg .substring ("-targetroot:" .length ());
50+ if (argValue .equals (JAVAC_CLASSES_DIR_ARG )) {
51+ useJavacClassesDir = true ;
52+ result .targetroot = getJavacClassesDir (result , ctx );
53+ } else {
54+ result .targetroot = Paths .get (argValue );
55+ }
3456 } else if (arg .startsWith ("-sourceroot:" )) {
3557 result .sourceroot = Paths .get (arg .substring ("-sourceroot:" .length ())).normalize ();
3658 } else if (arg .equals ("-text:on" )) {
@@ -47,12 +69,32 @@ public static SemanticdbJavacOptions parse(String[] args) {
4769 result .errors .add (String .format ("unknown flag '%s'\n " , arg ));
4870 }
4971 }
50- if (result .targetroot == null ) {
72+ if (result .targetroot == null && ! useJavacClassesDir ) {
5173 result .errors .add (missingRequiredDirectoryOption ("targetroot" ));
5274 }
5375 if (result .sourceroot == null ) {
5476 result .errors .add (missingRequiredDirectoryOption ("sourceroot" ));
5577 }
5678 return result ;
5779 }
80+
81+ private static Path getJavacClassesDir (SemanticdbJavacOptions result , Context ctx ) {
82+ // I'm not aware of a better way to get the class output directory from javac
83+ Path outputDir = null ;
84+ try {
85+ JavaFileManager fm = ctx .get (JavaFileManager .class );
86+ FileObject outputDirStub =
87+ fm .getJavaFileForOutput (CLASS_OUTPUT , stubClassName , JavaFileObject .Kind .CLASS , null );
88+ outputDir = Paths .get (outputDirStub .toUri ()).toAbsolutePath ().getParent ();
89+ } catch (Exception e ) {
90+ String errorMsg =
91+ String .format (
92+ "-targetroot:%s passed but could not get the class output directory: %s" ,
93+ JAVAC_CLASSES_DIR_ARG ,
94+ e .getMessage ()
95+ );
96+ result .errors .add (errorMsg );
97+ }
98+ return outputDir ;
99+ }
58100}
0 commit comments