33import java .io .*;
44import java .net .URI ;
55import java .nio .file .Path ;
6- import java .time . Instant ;
6+ import java .util . concurrent . atomic . AtomicLong ;
77import javax .lang .model .element .Modifier ;
88import javax .lang .model .element .NestingKind ;
99import javax .tools .JavaFileObject ;
@@ -13,20 +13,31 @@ public class SourceFileObject implements JavaFileObject {
1313 final Path path ;
1414 /** contents is the text in this file, or null if we should use the text in FileStore */
1515 final String contents ;
16- /** if contents is set, the modified time of contents */
17- final Instant modified ;
16+ /** if contents is set, the modified version of contents in monotonic nanoseconds */
17+ final long modified ;
18+ private static final AtomicLong LAST_NOW = new AtomicLong ();
1819
1920 public SourceFileObject (Path path ) {
20- this (path , null , Instant . EPOCH );
21+ this (path , null , 0 );
2122 }
2223
23- public SourceFileObject (Path path , String contents , Instant modified ) {
24+ public SourceFileObject (Path path , String contents , long modified ) {
2425 if (!FileStore .isJavaFile (path )) throw new RuntimeException (path + " is not a java source" );
2526 this .path = path ;
2627 this .contents = contents ;
2728 this .modified = modified ;
2829 }
2930
31+ public static long now () {
32+ while (true ) {
33+ var previous = LAST_NOW .get ();
34+ var candidate = Math .max (System .nanoTime (), previous + 1 );
35+ if (LAST_NOW .compareAndSet (previous , candidate )) {
36+ return candidate ;
37+ }
38+ }
39+ }
40+
3041 @ Override
3142 public boolean equals (Object other ) {
3243 if (other .getClass () != SourceFileObject .class ) return false ;
@@ -117,7 +128,7 @@ public Writer openWriter() {
117128 @ Override
118129 public long getLastModified () {
119130 if (contents != null ) {
120- return modified . toEpochMilli () ;
131+ return modified ;
121132 }
122133 var fileModified = FileStore .modified (path );
123134 if (fileModified == null ) return 0 ;
0 commit comments