99import com .sun .tools .javac .api .JavacTool ;
1010import com .sun .tools .javac .file .JavacFileManager ;
1111import com .sun .tools .javadoc .api .JavadocTool ;
12+ import java .time .Instant ;
1213import org .eclipse .lsp4j .CompletionItem ;
1314
1415import javax .lang .model .element .Element ;
@@ -49,7 +50,17 @@ public class Javadocs {
4950 /**
5051 * All the classes we have indexed so far
5152 */
52- private final Map <String , RootDoc > topLevelClasses = new ConcurrentHashMap <>();
53+ private final Map <String , IndexedDoc > topLevelClasses = new ConcurrentHashMap <>();
54+
55+ private static class IndexedDoc {
56+ final RootDoc doc ;
57+ final Instant updated ;
58+
59+ IndexedDoc (RootDoc doc , Instant updated ) {
60+ this .doc = doc ;
61+ this .updated = updated ;
62+ }
63+ }
5364
5465 private final JavacTask task ;
5566
@@ -229,53 +240,44 @@ Optional<ClassDoc> classDoc(String className) {
229240 return Optional .ofNullable (index .classNamed (className ));
230241 }
231242
232- void update (JavaFileObject source ) {
233- LOG .info ("Update javadocs for " + source .toUri ());
234-
235- DocumentationTool .DocumentationTask task = new JavadocTool ().getTask (
236- null ,
237- emptyFileManager ,
238- Javadocs ::onDiagnostic ,
239- Javadocs .class ,
240- ImmutableList .of ("-private" ),
241- ImmutableList .of (source )
242- );
243-
244- task .call ();
243+ /**
244+ * Get or compute the javadoc for `className`
245+ */
246+ RootDoc index (String className ) {
247+ if (needsUpdate (className ))
248+ topLevelClasses .put (className , doIndex (className ));
245249
246- getSneakyReturn (). ifPresent ( root -> updateCache ( root , source )) ;
250+ return topLevelClasses . get ( className ). doc ;
247251 }
248252
249- private void updateCache (RootDoc root , JavaFileObject source ) {
250- for (ClassDoc each : root .classes ()) {
251- if (source .isNameCompatible (each .simpleTypeName (), JavaFileObject .Kind .SOURCE )) {
252- topLevelClasses .put (each .qualifiedName (), root );
253+ private boolean needsUpdate (String className ) {
254+ if (!topLevelClasses .containsKey (className ))
255+ return true ;
253256
254- return ;
255- }
256- }
257- }
257+ IndexedDoc indexed = topLevelClasses .get (className );
258+
259+ try {
260+ JavaFileObject fromDisk = actualFileManager .getJavaFileForInput (StandardLocation .SOURCE_PATH , className , JavaFileObject .Kind .SOURCE );
261+ Instant modified = Instant .ofEpochMilli (fromDisk .getLastModified ());
258262
259- /**
260- * Get or compute the javadoc for `className`
261- */
262- RootDoc index (String className ) {
263- return topLevelClasses .computeIfAbsent (className , this ::doIndex );
263+ return indexed .updated .isBefore (modified );
264+ } catch (IOException e ) {
265+ throw new RuntimeException ();
266+ }
264267 }
265268
266269 /**
267270 * Read all the Javadoc for `className`
268271 */
269- private RootDoc doIndex (String className ) {
272+ private IndexedDoc doIndex (String className ) {
270273 try {
271274 JavaFileObject fromDisk = actualFileManager .getJavaFileForInput (StandardLocation .SOURCE_PATH , className , JavaFileObject .Kind .SOURCE );
272275
273276 if (fromDisk == null ) {
274277 LOG .warning ("No source file for " + className );
275278
276- return EmptyRootDoc .INSTANCE ;
279+ return new IndexedDoc ( EmptyRootDoc .INSTANCE , Instant . EPOCH ) ;
277280 }
278-
279281 JavaFileObject source = activeFile (fromDisk );
280282
281283 LOG .info ("Found " + source .toUri () + " for " + className );
@@ -290,11 +292,11 @@ private RootDoc doIndex(String className) {
290292 );
291293
292294 task .call ();
295+
296+ return new IndexedDoc (getSneakyReturn ().orElse (EmptyRootDoc .INSTANCE ), Instant .ofEpochMilli (fromDisk .getLastModified ()));
293297 } catch (IOException e ) {
294298 throw new RuntimeException ();
295299 }
296-
297- return getSneakyReturn ().orElse (EmptyRootDoc .INSTANCE );
298300 }
299301
300302 private JavaFileObject activeFile (JavaFileObject file ) {
0 commit comments