mirror of
https://github.com/dlang/tools.git
synced 2025-04-27 05:30:35 +03:00
Support parsing only specific unittests (e.g. @betterc-test)
This commit is contained in:
parent
28729b555d
commit
ca5384dd1b
4 changed files with 135 additions and 13 deletions
|
@ -107,8 +107,10 @@ $(ROOT)/tests_extractor: tests_extractor.d
|
|||
################################################################################
|
||||
|
||||
test_tests_extractor: $(ROOT)/tests_extractor
|
||||
$< -i ./test/tests_extractor/ascii.d | diff - ./test/tests_extractor/ascii.d.ext
|
||||
$< -i ./test/tests_extractor/iteration.d | diff - ./test/tests_extractor/iteration.d.ext
|
||||
for file in ascii iteration ; do \
|
||||
$< -i "./test/tests_extractor/$${file}.d" | diff -p - "./test/tests_extractor/$${file}.d.ext"; \
|
||||
done
|
||||
$< -a betterc -i "./test/tests_extractor/attributes.d" | diff -p - "./test/tests_extractor/attributes.d.ext";
|
||||
|
||||
RDMD_TEST_COMPILERS = $(DMD)
|
||||
RDMD_TEST_EXECUTABLE = $(ROOT)/rdmd
|
||||
|
|
44
test/tests_extractor/attributes.d
Normal file
44
test/tests_extractor/attributes.d
Normal file
|
@ -0,0 +1,44 @@
|
|||
module attributes;
|
||||
|
||||
enum betterc;
|
||||
|
||||
@betterc @safe @("foo") unittest
|
||||
{
|
||||
assert(1 == 1);
|
||||
}
|
||||
|
||||
@safe @("foo") unittest
|
||||
{
|
||||
assert(2 == 2);
|
||||
}
|
||||
|
||||
///
|
||||
@("foo") unittest
|
||||
{
|
||||
assert(3 == 3);
|
||||
}
|
||||
|
||||
@("foo") @betterc unittest
|
||||
{
|
||||
assert(4 == 4);
|
||||
}
|
||||
|
||||
@("betterc") @([1, 2, 3]) unittest
|
||||
{
|
||||
assert(5 == 5);
|
||||
}
|
||||
|
||||
@nogc @("foo", "betterc", "bar") @safe unittest
|
||||
{
|
||||
assert(6 == 6);
|
||||
}
|
||||
|
||||
@nogc @("foo", "better", "bar") @safe unittest
|
||||
{
|
||||
assert(7 == 7);
|
||||
}
|
||||
|
||||
@("betterd") unittest
|
||||
{
|
||||
assert(8 == 8);
|
||||
}
|
32
test/tests_extractor/attributes.d.ext
Normal file
32
test/tests_extractor/attributes.d.ext
Normal file
|
@ -0,0 +1,32 @@
|
|||
# line 3
|
||||
unittest
|
||||
{
|
||||
import attributes;
|
||||
|
||||
assert(1 == 1);
|
||||
}
|
||||
|
||||
# line 19
|
||||
unittest
|
||||
{
|
||||
import attributes;
|
||||
|
||||
assert(4 == 4);
|
||||
}
|
||||
|
||||
# line 24
|
||||
unittest
|
||||
{
|
||||
import attributes;
|
||||
|
||||
assert(5 == 5);
|
||||
}
|
||||
|
||||
# line 29
|
||||
unittest
|
||||
{
|
||||
import attributes;
|
||||
|
||||
assert(6 == 6);
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@ dependency "libdparse" version="~>0.8.0"
|
|||
* Parses all public unittests that are visible on dlang.org
|
||||
* (= annotated with three slashes)
|
||||
*
|
||||
* Copyright (C) 2017 by D Language Foundation
|
||||
* Copyright (C) 2018 by D Language Foundation
|
||||
*
|
||||
* Author: Sebastian Wilzbach
|
||||
*
|
||||
|
@ -33,11 +33,13 @@ class TestVisitor : ASTVisitor
|
|||
File outFile;
|
||||
ubyte[] sourceCode;
|
||||
string moduleName;
|
||||
string[] attributes;
|
||||
|
||||
this(File outFile, ubyte[] sourceCode)
|
||||
this(File outFile, ubyte[] sourceCode, string[] attributes)
|
||||
{
|
||||
this.outFile = outFile;
|
||||
this.sourceCode = sourceCode;
|
||||
this.attributes = attributes;
|
||||
}
|
||||
|
||||
alias visit = ASTVisitor.visit;
|
||||
|
@ -58,13 +60,51 @@ class TestVisitor : ASTVisitor
|
|||
|
||||
override void visit(const Declaration decl)
|
||||
{
|
||||
if (decl.unittest_ !is null && hasDdocHeader(sourceCode, decl))
|
||||
if (decl.unittest_ !is null && shouldIncludeUnittest(decl))
|
||||
print(decl.unittest_);
|
||||
|
||||
decl.accept(this);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool shouldIncludeUnittest(const Declaration decl)
|
||||
{
|
||||
if (!attributes.empty)
|
||||
return filterForUDAs(decl);
|
||||
else
|
||||
return hasDdocHeader(sourceCode, decl);
|
||||
}
|
||||
|
||||
bool filterForUDAs(const Declaration decl)
|
||||
{
|
||||
foreach (attr; decl.attributes)
|
||||
{
|
||||
// check for @myArg
|
||||
if (attributes.canFind(attr.atAttribute.identifier.text))
|
||||
return true;
|
||||
|
||||
// support @("myArg") too
|
||||
if (auto argList = attr.atAttribute.argumentList)
|
||||
{
|
||||
foreach (arg; argList.items)
|
||||
{
|
||||
if (auto unaryExp = cast(UnaryExpression) arg)
|
||||
if (auto primaryExp = unaryExp.primaryExpression)
|
||||
{
|
||||
auto attribute = primaryExp.primary.text;
|
||||
if (attribute.length >= 2)
|
||||
{
|
||||
attribute = attribute[1 .. $ - 1];
|
||||
if (attributes.canFind(attribute))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void print(const Unittest u)
|
||||
{
|
||||
/*
|
||||
|
@ -93,7 +133,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
void parseFile(File inFile, File outFile)
|
||||
void parseFile(File inFile, File outFile, string[] attributes)
|
||||
{
|
||||
import dparse.lexer;
|
||||
import dparse.parser : parseModule;
|
||||
|
@ -111,11 +151,11 @@ void parseFile(File inFile, File outFile)
|
|||
|
||||
RollbackAllocator rba;
|
||||
auto m = parseModule(tokens.array, inFile.name, &rba);
|
||||
auto visitor = new TestVisitor(outFile, sourceCode);
|
||||
auto visitor = new TestVisitor(outFile, sourceCode, attributes);
|
||||
visitor.visit(m);
|
||||
}
|
||||
|
||||
void parseFileDir(string inputDir, string fileName, string outputDir)
|
||||
void parseFileDir(string inputDir, string fileName, string outputDir, string[] attributes)
|
||||
{
|
||||
import std.path : buildPath, dirSeparator, buildNormalizedPath;
|
||||
|
||||
|
@ -132,7 +172,7 @@ void parseFileDir(string inputDir, string fileName, string outputDir)
|
|||
// convert the file path to a nice output file, e.g. std/uni.d -> std_uni.d
|
||||
string outName = fileNameNormalized.replace(dirSeparator, "_");
|
||||
|
||||
parseFile(File(fileName), File(buildPath(outputDir, outName), "w"));
|
||||
parseFile(File(fileName), File(buildPath(outputDir, outName), "w"), attributes);
|
||||
}
|
||||
|
||||
void main(string[] args)
|
||||
|
@ -143,12 +183,15 @@ void main(string[] args)
|
|||
string inputDir;
|
||||
string outputDir = "./out";
|
||||
string ignoredFilesStr;
|
||||
string modulePrefix = "";
|
||||
string modulePrefix;
|
||||
string attributesStr;
|
||||
|
||||
auto helpInfo = getopt(args, config.required,
|
||||
"inputdir|i", "Folder to start the recursive search for unittest blocks (can be a single file)", &inputDir,
|
||||
"outputdir|o", "Folder to which the extracted test files should be saved (stdout for a single file)", &outputDir,
|
||||
"ignore", "Comma-separated list of files to exclude (partial matching is supported)", &ignoredFilesStr);
|
||||
"ignore", "Comma-separated list of files to exclude (partial matching is supported)", &ignoredFilesStr,
|
||||
"attributes|a", "Comma-separated list of UDAs that the unittest should have", &attributesStr,
|
||||
);
|
||||
|
||||
if (helpInfo.helpWanted)
|
||||
{
|
||||
|
@ -162,6 +205,7 @@ to in the output directory.
|
|||
|
||||
inputDir = inputDir.asNormalizedPath.array;
|
||||
Algebraic!(string, File) outputLocation = cast(string) outputDir.asNormalizedPath.array;
|
||||
auto attributes = attributesStr.split(",");
|
||||
|
||||
if (!exists(outputDir))
|
||||
mkdir(outputDir);
|
||||
|
@ -196,8 +240,8 @@ to in the output directory.
|
|||
{
|
||||
stderr.writeln("parsing ", file);
|
||||
outputLocation.visit!(
|
||||
(string outputFolder) => parseFileDir(inputDir, file, outputFolder),
|
||||
(File outputFile) => parseFile(File(file.name, "r"), outputFile),
|
||||
(string outputFolder) => parseFileDir(inputDir, file, outputFolder, attributes),
|
||||
(File outputFile) => parseFile(File(file.name, "r"), outputFile, attributes),
|
||||
);
|
||||
}
|
||||
else
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue