88import javax .lang .model .util .Types ;
99
1010import javax .tools .JavaFileObject ;
11- import java .io .ByteArrayOutputStream ;
12- import java .io .IOException ;
13- import java .io .PrintWriter ;
11+ import java .io .*;
1412import java .net .URI ;
1513import java .nio .file .Files ;
1614import java .nio .file .Path ;
1715import java .nio .file .Paths ;
16+ import java .util .HashSet ;
17+ import java .util .Set ;
18+ import java .util .stream .Collectors ;
1819
1920/**
2021 * Callback hook that generates SemanticDB when the compiler has completed typechecking a Java
@@ -48,6 +49,7 @@ public void started(TaskEvent e) {}
4849
4950 @ Override
5051 public void finished (TaskEvent e ) {
52+ // System.out.println("Finishing " + e.getKind() + " on " + e.getSourceFile());
5153 if (e .getKind () != TaskEvent .Kind .ANALYZE ) return ;
5254 if (!options .errors .isEmpty ()) {
5355 if (!options .alreadyReportedErrors ) {
@@ -78,8 +80,10 @@ public void finished(TaskEvent e) {
7880 }
7981 }
8082
81- // Uses reporter.error with the full stack trace of the exception instead of reporter.exception
82- // because reporter.exception doesn't seem to print any meaningful information about the
83+ // Uses reporter.error with the full stack trace of the exception instead of
84+ // reporter.exception
85+ // because reporter.exception doesn't seem to print any meaningful information
86+ // about the
8387 // exception, it just prints the location with an empty message.
8488 private void reportException (Throwable exception , TaskEvent e ) {
8589 ByteArrayOutputStream baos = new ByteArrayOutputStream ();
@@ -93,7 +97,7 @@ private void onFinishedAnalyze(TaskEvent e) {
9397 Result <Path , String > path = semanticdbOutputPath (options , e );
9498 if (path != null ) {
9599 if (path .isOk ()) {
96- System .out .println ("Triggering for " + path .getOrThrow () + e .toString ());
100+ // System.out.println("Triggering for " + path.getOrThrow() + e.toString());
97101 Semanticdb .TextDocument textDocument =
98102 new SemanticdbVisitor (globals , e .getCompilationUnit (), options , types , trees , elements )
99103 .buildTextDocument (e .getCompilationUnit ());
@@ -105,13 +109,54 @@ private void onFinishedAnalyze(TaskEvent e) {
105109 }
106110
107111 private void writeSemanticdb (TaskEvent event , Path output , Semanticdb .TextDocument textDocument ) {
108- try {
112+ if (output .toFile ().exists ()) {
113+ // APPEND
114+ Semanticdb .TextDocuments documents = null ;
115+ try (InputStream is = Files .newInputStream (output .toFile ().toPath ())) {
116+
117+ documents = Semanticdb .TextDocuments .parseFrom (is );
118+
119+ } catch (IOException e ) {
120+ this .reportException (e , event );
121+ System .out .println (e );
122+ return ;
123+ }
124+
125+ Semanticdb .TextDocument document = documents .getDocuments (0 );
126+
127+ Set <Semanticdb .SymbolInformation > symbols = new HashSet <>(document .getSymbolsList ());
128+ Set <Semanticdb .SymbolOccurrence > occurrences = new HashSet <>(document .getOccurrencesList ());
129+
130+ symbols .addAll (textDocument .getSymbolsList ());
131+ occurrences .addAll (textDocument .getOccurrencesList ());
132+
133+ Semanticdb .TextDocument finalDocument =
134+ document
135+ .toBuilder ()
136+ .clearOccurrences ()
137+ .addAllOccurrences (occurrences )
138+ .clearSymbols ()
139+ .addAllSymbols (symbols )
140+ .build ();
141+
109142 byte [] bytes =
110- Semanticdb .TextDocuments .newBuilder ().addDocuments (textDocument ).build ().toByteArray ();
111- Files .createDirectories (output .getParent ());
112- Files .write (output , bytes );
113- } catch (IOException e ) {
114- this .reportException (e , event );
143+ Semanticdb .TextDocuments .newBuilder ().addDocuments (finalDocument ).build ().toByteArray ();
144+
145+ try {
146+ Files .createDirectories (output .getParent ());
147+ Files .write (output , bytes );
148+ } catch (IOException e ) {
149+ this .reportException (e , event );
150+ }
151+ } else { // OVERWRITE
152+ try {
153+ byte [] bytes =
154+ Semanticdb .TextDocuments .newBuilder ().addDocuments (textDocument ).build ().toByteArray ();
155+ Files .createDirectories (output .getParent ());
156+ Files .write (output , bytes );
157+ } catch (IOException e ) {
158+ this .reportException (e , event );
159+ }
115160 }
116161 }
117162
@@ -211,10 +256,13 @@ private Result<Path, String> semanticdbOutputPath(SemanticdbJavacOptions options
211256
212257 switch (options .noRelativePath ) {
213258 case INDEX_ANYWAY :
214- // Come up with a unique relative path for this file even if it's not under the sourceroot.
215- // By indexing auto-generated files, we collect SymbolInformation for auto-generated symbol,
259+ // Come up with a unique relative path for this file even if it's not under the
260+ // sourceroot.
261+ // By indexing auto-generated files, we collect SymbolInformation for
262+ // auto-generated symbol,
216263 // which results in more useful hover tooltips in the editor.
217- // In the future, we may want to additionally embed the full text contents of these files
264+ // In the future, we may want to additionally embed the full text contents of
265+ // these files
218266 // so that it's possible to browse generated files with precise code navigation.
219267 String uniqueFilename =
220268 String .format ("%d.%s.semanticdb" , ++noRelativePathCounter , absolutePath .getFileName ());
0 commit comments