@@ -7,7 +7,7 @@ dependency "libdparse" version="~>0.8.0"
77 * Parses all public unittests that are visible on dlang.org
88 * (= annotated with three slashes)
99 *
10- * Copyright (C) 2017 by D Language Foundation
10+ * Copyright (C) 2018 by D Language Foundation
1111 *
1212 * Author: Sebastian Wilzbach
1313 *
@@ -33,11 +33,13 @@ class TestVisitor : ASTVisitor
3333 File outFile;
3434 ubyte [] sourceCode;
3535 string moduleName;
36+ string [] attributes;
3637
37- this (File outFile, ubyte [] sourceCode)
38+ this (File outFile, ubyte [] sourceCode, string [] attributes )
3839 {
3940 this .outFile = outFile;
4041 this .sourceCode = sourceCode;
42+ this .attributes = attributes;
4143 }
4244
4345 alias visit = ASTVisitor.visit;
@@ -58,13 +60,51 @@ class TestVisitor : ASTVisitor
5860
5961 override void visit (const Declaration decl)
6062 {
61- if (decl.unittest_ ! is null && hasDdocHeader(sourceCode, decl))
63+ if (decl.unittest_ ! is null && shouldIncludeUnittest( decl))
6264 print(decl.unittest_);
6365
6466 decl.accept(this );
6567 }
6668
6769private :
70+
71+ bool shouldIncludeUnittest (const Declaration decl)
72+ {
73+ if (! attributes.empty)
74+ return filterForUDAs (decl);
75+ else
76+ return hasDdocHeader (sourceCode, decl);
77+ }
78+
79+ bool filterForUDAs (const Declaration decl)
80+ {
81+ foreach (attr; decl.attributes)
82+ {
83+ // check for @myArg
84+ if (attributes.canFind(attr.atAttribute.identifier.text))
85+ return true ;
86+
87+ // support @("myArg") too
88+ if (auto argList = attr.atAttribute.argumentList)
89+ {
90+ foreach (arg; argList.items)
91+ {
92+ if (auto unaryExp = cast (UnaryExpression) arg)
93+ if (auto primaryExp = unaryExp.primaryExpression)
94+ {
95+ auto attribute = primaryExp.primary.text;
96+ if (attribute.length >= 2 )
97+ {
98+ attribute = attribute[1 .. $ - 1 ];
99+ if (attributes.canFind(attribute))
100+ return true ;
101+ }
102+ }
103+ }
104+ }
105+ }
106+ return false ;
107+ }
68108 void print (const Unittest u)
69109 {
70110 /*
@@ -93,7 +133,7 @@ private:
93133 }
94134}
95135
96- void parseFile (File inFile, File outFile)
136+ void parseFile (File inFile, File outFile, string [] attributes )
97137{
98138 import dparse.lexer;
99139 import dparse.parser : parseModule;
@@ -111,11 +151,11 @@ void parseFile(File inFile, File outFile)
111151
112152 RollbackAllocator rba;
113153 auto m = parseModule(tokens.array, inFile.name, &rba);
114- auto visitor = new TestVisitor(outFile, sourceCode);
154+ auto visitor = new TestVisitor(outFile, sourceCode, attributes );
115155 visitor.visit(m);
116156}
117157
118- void parseFileDir (string inputDir, string fileName, string outputDir)
158+ void parseFileDir (string inputDir, string fileName, string outputDir, string [] attributes )
119159{
120160 import std.path : buildPath, dirSeparator, buildNormalizedPath;
121161
@@ -132,7 +172,7 @@ void parseFileDir(string inputDir, string fileName, string outputDir)
132172 // convert the file path to a nice output file, e.g. std/uni.d -> std_uni.d
133173 string outName = fileNameNormalized.replace(dirSeparator, " _" );
134174
135- parseFile(File (fileName), File (buildPath(outputDir, outName), " w" ));
175+ parseFile(File (fileName), File (buildPath(outputDir, outName), " w" ), attributes );
136176}
137177
138178void main (string [] args)
@@ -143,12 +183,15 @@ void main(string[] args)
143183 string inputDir;
144184 string outputDir = " ./out" ;
145185 string ignoredFilesStr;
146- string modulePrefix = " " ;
186+ string modulePrefix;
187+ string attributesStr;
147188
148189 auto helpInfo = getopt(args, config.required,
149190 " inputdir|i" , " Folder to start the recursive search for unittest blocks (can be a single file)" , &inputDir,
150191 " outputdir|o" , " Folder to which the extracted test files should be saved (stdout for a single file)" , &outputDir,
151- " ignore" , " Comma-separated list of files to exclude (partial matching is supported)" , &ignoredFilesStr);
192+ " ignore" , " Comma-separated list of files to exclude (partial matching is supported)" , &ignoredFilesStr,
193+ " attributes|a" , " Comma-separated list of UDAs that the unittest should have" , &attributesStr,
194+ );
152195
153196 if (helpInfo.helpWanted)
154197 {
@@ -162,6 +205,7 @@ to in the output directory.
162205
163206 inputDir = inputDir.asNormalizedPath.array;
164207 Algebraic! (string , File ) outputLocation = cast (string ) outputDir.asNormalizedPath.array;
208+ auto attributes = attributesStr.split(" ," );
165209
166210 if (! exists(outputDir))
167211 mkdir(outputDir);
@@ -196,8 +240,8 @@ to in the output directory.
196240 {
197241 stderr.writeln(" parsing " , file);
198242 outputLocation.visit! (
199- (string outputFolder) => parseFileDir(inputDir, file, outputFolder),
200- (File outputFile) => parseFile(File (file.name, " r" ), outputFile),
243+ (string outputFolder) => parseFileDir(inputDir, file, outputFolder, attributes ),
244+ (File outputFile) => parseFile(File (file.name, " r" ), outputFile, attributes ),
201245 );
202246 }
203247 else
0 commit comments