8
8
module gchunt ;
9
9
10
10
import std.algorithm , std.conv , std.stdio , std.string , std.exception ,
11
- std.regex , std.range , std.process ;
11
+ std.regex , std.range , std.process , std.getopt ;
12
12
13
13
static import std.file ;
14
14
15
15
// libdparse:
16
- import std.d .lexer ;
16
+ import dparse .lexer;
17
17
// our pattern matching on D tokens
18
18
import revdpattern;
19
19
@@ -192,9 +192,9 @@ unittest{
192
192
assert (matchPattern(" aaaafdsfbbbasd" , " aaaa*b*" ));
193
193
}
194
194
195
- BlacklistEntry[] blacklist;
195
+ BlacklistEntry[] blacklist; //
196
196
197
- Comment[] talk; // comments
197
+ // comments
198
198
199
199
struct Reason {
200
200
string reason;
@@ -212,7 +212,8 @@ struct Artifact{
212
212
Artifact[string ] artifacts;
213
213
214
214
// load comments from wiki dump
215
- void loadComments (string path){
215
+ Comment[] loadComments (string path){
216
+ Comment[] talk;
216
217
auto lines = File (path).byLine.map! (x => x.idup).array;
217
218
string [] record;
218
219
foreach (i, line; lines){
@@ -232,15 +233,18 @@ void loadComments(string path){
232
233
if (m)
233
234
record ~= m[1 ];
234
235
}
236
+ return talk;
235
237
}
236
238
237
239
version (unittest ) void main(){}
238
- else void main(){
239
- string fmt = " mediawiki" ;
240
- string gitHost = ` https://github.com` ;
241
- string gitHash = gitHEAD();
242
- string gitRepo = gitRemotePath();
240
+ else void main(string [] args){
241
+ bool graphMode = false ;
242
+
243
243
auto re = regex(` (.*[\\/]\w+)\.d\((\d+)\):\s*vgc:\s*(.*)` );
244
+ auto opts = getopt(args, " graph" , &graphMode);
245
+ if (opts.helpWanted){
246
+ defaultGetoptPrinter(" gchunt - pinpoint GC usage in D apps" , opts.options);
247
+ }
244
248
Result[] results;
245
249
foreach (line; stdin.byLine){
246
250
auto m = line.idup.matchFirst(re);
@@ -251,19 +255,15 @@ else void main(){
251
255
sort! ((a,b) => a.file < b.file || (a.file == b.file && a.line < b.line))
252
256
(results);
253
257
254
- results = uniq(results).array;
258
+ results = uniq(results).array; // deduplicate
259
+ // Tokenize modules in question
255
260
auto interned = StringCache(4096 );
256
261
foreach (mod;results.map! (x => x.file).uniq){
257
262
auto config = LexerConfig(mod~ " .d" , StringBehavior.compiler);
258
263
auto data = cast (ubyte [])std.file.read (mod ~ " .d" );
259
264
tokenStreams[mod] = getTokensForParser(data, config, &interned).dup ;
260
265
// TODO: generate new "vgc" records for each .(i)dup
261
266
}
262
- try {
263
- loadComments(" talk.gchunt" );
264
- stderr.writefln(" talk.gchunt loaded: %d comments." , talk.length);
265
- }
266
- catch (Exception ){} // was that FileException?
267
267
try {
268
268
auto f = File (" blacklist.gchunt" );
269
269
stderr.writeln(" Found blacklist.gchunt ..." );
@@ -276,67 +276,84 @@ else void main(){
276
276
stderr.writefln(" blacklist.gchunt loaded: %d patterns." , blacklist.length);
277
277
}
278
278
catch (Exception ){}
279
- foreach (r; results){
280
- // writeln(r.file, ",", r.line, ",", r.reason);
281
- auto mod = r.file.replace(" /" , " ." );
282
- auto artifact = findArtifact(r);
283
- auto path = mod~ " :" ~ artifact;
284
- if (path ! in artifacts){
285
- artifacts[path] = Artifact(artifact, mod);
279
+ if (graphMode){
280
+
281
+ }
282
+ else {
283
+ string fmt = " mediawiki" ;
284
+ string gitHost = ` https://github.com` ;
285
+ string gitHash = gitHEAD();
286
+ string gitRepo = gitRemotePath();
287
+ Comment[] talk;
288
+ try {
289
+ talk = loadComments(" talk.gchunt" );
290
+ stderr.writefln(" talk.gchunt loaded: %d comments." , talk.length);
286
291
}
287
- auto idx = artifacts[path].reasons.countUntil! (x => x.reason == r.reason);
288
- if (idx < 0 ) {
289
- artifacts[path].reasons ~= Reason(r.reason, [to! int (r.line)]);
292
+ catch (Exception ){} // was that FileException?
293
+ foreach (r; results){
294
+ // writeln(r.file, ",", r.line, ",", r.reason);
295
+ auto mod = r.file.replace(" /" , " ." );
296
+ auto artifact = findArtifact(r);
297
+ auto path = mod~ " :" ~ artifact;
298
+ if (path ! in artifacts){
299
+ artifacts[path] = Artifact(artifact, mod);
300
+ }
301
+ auto idx = artifacts[path].reasons.countUntil! (x => x.reason == r.reason);
302
+ if (idx < 0 ) {
303
+ artifacts[path].reasons ~= Reason(r.reason, [to! int (r.line)]);
304
+ }
305
+ else
306
+ artifacts[path].reasons[idx].locs ~= to! int (r.line);
290
307
}
291
- else
292
- artifacts[path].reasons[idx].locs ~= to! int (r.line);
293
- }
294
- auto accum = artifacts.values ();
295
- accum.sort! ((a,b) => a.mod < b.mod || (a.mod == b.mod && a.id < b.id));
308
+ auto accum = artifacts.values ();
309
+ accum.sort! ((a,b) => a.mod < b.mod || (a.mod == b.mod && a.id < b.id));
296
310
297
- string linkTemplate =
298
- ` [%s/%s/blob/%s/%s.d#L%s %d] ` ;
299
- writeln(`
300
- {| class="wikitable"
301
- ! Module
302
- ! Artifact
303
- ! Reason
304
- ! Possible Fix(es)
305
- |-` );
306
- stderr.writefln(" Total number of GC-happy artifacts: %s." , accum.length);
307
- int attached = 0 ;
308
- foreach (ref art; accum){
309
- string [] comments;
310
- foreach (i, t; talk)
311
- if (t.mod == art.mod && art.id == t.artifact){
312
- comments ~= t.comment;
311
+ string linkTemplate =
312
+ ` [%s/%s/blob/%s/%s.d#L%s %d] ` ;
313
+ writeln(`
314
+ {| class="wikitable"
315
+ ! Module
316
+ ! Artifact
317
+ ! Reason
318
+ ! Possible Fix(es)
319
+ |-` );
320
+ stderr.writefln(" Total number of GC-happy artifacts: %s." , accum.length);
321
+ int attached = 0 ;
322
+ foreach (ref art; accum){
323
+ string [] comments;
324
+ foreach (i, t; talk)
325
+ if (t.mod == art.mod && art.id == t.artifact){
326
+ comments ~= t.comment;
327
+ }
328
+ if (comments.length){
329
+ attached += comments.length;
330
+ art.comment = comments.sort().uniq().join(" ;" );
313
331
}
314
- if (comments.length){
315
- attached += comments.length;
316
- art.comment = comments.sort().uniq().join(" ;" );
317
- }
318
- }
319
- if (talk.length) // talk.gchunt file was loaded
320
- stderr.writefln(" Successfully attached %d comments." , attached);
321
- int filtered = 0 ;
322
- foreach (art; accum){
323
- if (blacklist.canFind! (black => black.match(art.mod, art.id))){
324
- filtered++ ;
325
- continue ; // skip over if matches blacklist
326
332
}
327
- art.reasons.sort! ((a,b) => a.reason < b.reason);
328
- string reason = art.reasons.map! ((r){
329
- string links = r.reason~ " :" ;
330
- foreach (i, loc; r.locs){
331
- links ~= format(linkTemplate, gitHost, gitRepo, gitHash,
332
- art.mod.replace(" ." ," /" ), loc, i+ 1 );
333
+ if (talk.length) // talk.gchunt file was loaded
334
+ stderr.writefln(" Successfully attached %d comments." , attached);
335
+ int filtered = 0 ;
336
+ foreach (art; accum){
337
+ if (blacklist.canFind! (black => black.match(art.mod, art.id))){
338
+ filtered++ ;
339
+ continue ; // skip over if matches blacklist
333
340
}
334
- return links;
335
- }).join(" \n\n " );
336
- writef(" |%s\n |%s\n |%s\n | %s\n |-\n " , art.mod, art.id,
337
- reason, art.comment);
341
+ art.reasons.sort! ((a,b) => a.reason < b.reason);
342
+ string reason = art.reasons.map! ((r){
343
+ string links = r.reason~ " :" ;
344
+ foreach (i, loc; r.locs){
345
+ links ~= format(linkTemplate, gitHost, gitRepo, gitHash,
346
+ art.mod.replace(" ." ," /" ), loc, i+ 1 );
347
+ }
348
+ return links;
349
+ }).join(" \n\n " );
350
+ writef(" |%s\n |%s\n |%s\n | %s\n |-\n " , art.mod, art.id,
351
+ reason, art.comment);
352
+ }
353
+ writeln(" |}" );
354
+ if (blacklist.length)
355
+ stderr.writefln(" Filtered %d artifacts." , filtered);
338
356
}
339
- writeln(" |}" );
340
- if (blacklist.length)
341
- stderr.writefln(" Filtered %d artifacts." , filtered);
357
+
358
+
342
359
}
0 commit comments