26
26
import com .vertispan .j2cl .build .task .OutputTypes ;
27
27
import com .vertispan .j2cl .build .task .Project ;
28
28
import com .vertispan .j2cl .build .task .TaskFactory ;
29
- import com .vertispan .j2cl .tools .Closure ;
30
29
import io .methvin .watcher .hashing .Murmur3F ;
31
- import org .apache .commons .io .FileUtils ;
32
30
33
31
import java .io .BufferedInputStream ;
34
32
import java .io .BufferedReader ;
@@ -115,17 +113,9 @@ public Task resolve(Project project, Config config) {
115
113
return ;// nothing to do
116
114
}
117
115
118
- // copy the sources locally so that we can create usable sourcemaps
119
- //TODO consider a soft link
120
- File sources = new File (closureOutputDir , Closure .SOURCES_DIRECTORY_NAME );
121
- for (Path path : js .stream ().map (Input ::getParentPaths ).flatMap (Collection ::stream ).collect (Collectors .toUnmodifiableList ())) {
122
- FileUtils .copyDirectory (path .toFile (), sources );
123
- }
124
-
125
116
List <DependencyInfoAndSource > dependencyInfos = new ArrayList <>();
126
117
Compiler jsCompiler = new Compiler (System .err );//TODO before merge, write this to the log
127
118
128
- Path sourcesPath = context .outputPath ().resolve (Closure .SOURCES_DIRECTORY_NAME );
129
119
if (incrementalEnabled && context .lastSuccessfulOutput ().isPresent ()) {
130
120
// collect any dep info from disk for existing files
131
121
final Map <String , DependencyInfoAndSource > depInfoMap ;
@@ -135,9 +125,15 @@ public Task resolve(Project project, Config config) {
135
125
}.getType ();
136
126
List <DependencyInfoFormat > deps = gson .fromJson (new BufferedReader (new InputStreamReader (inputStream )), listType );
137
127
depInfoMap = deps .stream ()
138
- .map (info -> new DependencyInfoAndSource (
139
- info ,
140
- () -> Files .readString (lastOutput .resolve (Closure .SOURCES_DIRECTORY_NAME ).resolve (info .getName ())))
128
+ .map (info -> {
129
+ Path p = js .stream ().flatMap (jsInput -> jsInput .getParentPaths ().stream ())
130
+ .map (parent -> parent .resolve (info .getName ()))
131
+ .filter (Files ::exists )
132
+ .findFirst ().get ();
133
+ return new DependencyInfoAndSource (
134
+ p , info ,
135
+ () -> Files .readString (p ));
136
+ }
141
137
)
142
138
.collect (Collectors .toMap (DependencyInfo ::getName , Function .identity ()));
143
139
}
@@ -149,14 +145,18 @@ public Task resolve(Project project, Config config) {
149
145
depInfoMap .remove (change .getSourcePath ().toString ());
150
146
} else {
151
147
// ADD or MODIFY
148
+ Path p = jsInput .getParentPaths ().stream ()
149
+ .map (parent -> parent .resolve (change .getSourcePath ()))
150
+ .filter (Files ::exists )
151
+ .findFirst ().get ();
152
152
CompilerInput input = new CompilerInput (SourceFile .builder ()
153
- .withPath (sourcesPath . resolve ( change . getSourcePath ()) )
153
+ .withPath (p )
154
154
.withOriginalPath (change .getSourcePath ().toString ())
155
155
.build ());
156
156
input .setCompiler (jsCompiler );
157
157
depInfoMap .put (
158
158
change .getSourcePath ().toString (),
159
- new DependencyInfoAndSource (input , input ::getCode )
159
+ new DependencyInfoAndSource (p , input , input ::getCode )
160
160
);
161
161
}
162
162
}
@@ -170,13 +170,17 @@ public Task resolve(Project project, Config config) {
170
170
//non-incremental, read everything
171
171
for (Input jsInput : js ) {
172
172
for (CachedPath path : jsInput .getFilesAndHashes ()) {
173
+ Path p = jsInput .getParentPaths ().stream ()
174
+ .map (parent -> parent .resolve (path .getSourcePath ()))
175
+ .filter (Files ::exists )
176
+ .findFirst ().get ();
173
177
CompilerInput input = new CompilerInput (SourceFile .builder ()
174
- .withPath (sourcesPath . resolve ( path . getSourcePath ()) )
178
+ .withPath (p )
175
179
.withOriginalPath (path .getSourcePath ().toString ())
176
180
.build ());
177
181
input .setCompiler (jsCompiler );
178
182
179
- dependencyInfos .add (new DependencyInfoAndSource (input , input ::getCode ));
183
+ dependencyInfos .add (new DependencyInfoAndSource (p , input , input ::getCode ));
180
184
}
181
185
}
182
186
}
@@ -212,33 +216,35 @@ public Task resolve(Project project, Config config) {
212
216
for (DependencyInfoAndSource info : sorter .getSortedList ()) {
213
217
String code = info .getSource ();
214
218
String name = info .getName ();
215
- String sourcemapContents = info .loadSourcemap (sourcesPath );
219
+ String sourcemapContents = info .loadSourcemap ();
216
220
217
221
//TODO do we actually need this?
218
222
if (Compiler .isFillFileName (name ) && code .isEmpty ()) {
219
223
continue ;
220
224
}
221
225
226
+ // Append a note indicating the name of the JS file that will follow
222
227
writer .append ("//" ).append (name ).append ("\n " );
223
228
229
+ // Immediately before appending the JS file's contents, check which line we're starting at, and
230
+ // merge sourcemap contents
224
231
if (sourcemapContents != null ) {
225
232
sourceMapGenerator .setStartingPosition (writer .getLine (), 0 );
226
233
SourceMapConsumerV3 section = new SourceMapConsumerV3 ();
227
234
section .parse (sourcemapContents );
228
235
section .visitMappings ((sourceName , symbolName , sourceStartPosition , startPosition , endPosition ) -> sourceMapGenerator .addMapping (Paths .get (name ).resolveSibling (sourceName ).toString (), symbolName , sourceStartPosition , startPosition , endPosition ));
229
236
for (String source : section .getOriginalSources ()) {
230
- String content = Files .readString (sourcesPath . resolve ( name ).resolveSibling (source ));
237
+ String content = Files .readString (info . getAbsolutePath ( ).resolveSibling (source ));
231
238
sourceMapGenerator .addSourcesContent (Paths .get (name ).resolveSibling (source ).toString (), content );
232
239
}
233
240
}
234
241
235
- // append this file and a comment where it came from
242
+ // Append the current file
236
243
bundler .withPath (name ).appendTo (writer , info , code );
237
244
writer .append ("\n " );
238
245
}
239
246
240
247
// write a reference to our new sourcemaps
241
- // writer.append("// " + writer.getLine()).append("\n");
242
248
writer .append ("//# sourceMappingURL=" ).append (sourcemapOutFileName ).append ('\n' );
243
249
}
244
250
@@ -324,14 +330,20 @@ public interface SourceSupplier {
324
330
String get () throws IOException ;
325
331
}
326
332
public static class DependencyInfoAndSource implements DependencyInfo {
333
+ private final Path absolutePath ;
327
334
private final DependencyInfo delegate ;
328
335
private final SourceSupplier sourceSupplier ;
329
336
330
- public DependencyInfoAndSource (DependencyInfo delegate , SourceSupplier sourceSupplier ) {
337
+ public DependencyInfoAndSource (Path absolutePath , DependencyInfo delegate , SourceSupplier sourceSupplier ) {
338
+ this .absolutePath = absolutePath ;
331
339
this .delegate = delegate ;
332
340
this .sourceSupplier = sourceSupplier ;
333
341
}
334
342
343
+ public Path getAbsolutePath () {
344
+ return absolutePath ;
345
+ }
346
+
335
347
public String getSource () throws IOException {
336
348
return sourceSupplier .get ();
337
349
}
@@ -392,15 +404,15 @@ public boolean getHasNoCompileAnnotation() {
392
404
return delegate .getHasNoCompileAnnotation ();
393
405
}
394
406
395
- public String loadSourcemap (Path outPath ) throws IOException {
407
+ public String loadSourcemap () throws IOException {
396
408
String sourceMappingUrlMarker = "//# sourceMappingURL=" ;
397
409
int offset = getSource ().lastIndexOf (sourceMappingUrlMarker );
398
410
if (offset == -1 ) {
399
411
return null ;
400
412
}
401
413
int urlPos = offset + sourceMappingUrlMarker .length ();
402
414
String sourcemapName = getSource ().substring (urlPos ).split ("\\ s" )[0 ];
403
- return Files .readString (outPath . resolve ( getName ()) .resolveSibling (sourcemapName ));
415
+ return Files .readString (absolutePath .resolveSibling (sourcemapName ));
404
416
}
405
417
}
406
418
0 commit comments