mirror of
https://github.com/dlang/tools.git
synced 2025-04-28 22:21:14 +03:00
Merge pull request #303 from WebDrake/prevent-eval-loop-empty-statements
Prevent empty statements at the end of --eval or --loop code
This commit is contained in:
commit
a8d282e618
1 changed files with 98 additions and 7 deletions
105
rdmd.d
105
rdmd.d
|
@ -17,7 +17,7 @@
|
||||||
import std.algorithm, std.array, core.stdc.stdlib, std.datetime,
|
import std.algorithm, std.array, core.stdc.stdlib, std.datetime,
|
||||||
std.digest.md, std.exception, std.file, std.getopt,
|
std.digest.md, std.exception, std.file, std.getopt,
|
||||||
std.parallelism, std.path, std.process, std.range, std.regex,
|
std.parallelism, std.path, std.process, std.range, std.regex,
|
||||||
std.stdio, std.string, std.typetuple;
|
std.stdio, std.string, std.typecons, std.typetuple;
|
||||||
|
|
||||||
version (Posix)
|
version (Posix)
|
||||||
{
|
{
|
||||||
|
@ -180,18 +180,14 @@ int main(string[] args)
|
||||||
{
|
{
|
||||||
enforce(programPos == args.length, "Cannot have both --loop and a " ~
|
enforce(programPos == args.length, "Cannot have both --loop and a " ~
|
||||||
"program file ('" ~ args[programPos] ~ "').");
|
"program file ('" ~ args[programPos] ~ "').");
|
||||||
root = makeEvalFile(importWorld ~ "void main(char[][] args) { "
|
root = makeEvalFile(makeEvalCode(loop, Yes.loop));
|
||||||
~ "foreach (line; std.stdio.stdin.byLine()) {\n"
|
|
||||||
~ std.string.join(loop, "\n")
|
|
||||||
~ ";\n} }");
|
|
||||||
argsBeforeProgram ~= "-d";
|
argsBeforeProgram ~= "-d";
|
||||||
}
|
}
|
||||||
else if (eval.ptr)
|
else if (eval.ptr)
|
||||||
{
|
{
|
||||||
enforce(programPos == args.length, "Cannot have both --eval and a " ~
|
enforce(programPos == args.length, "Cannot have both --eval and a " ~
|
||||||
"program file ('" ~ args[programPos] ~ "').");
|
"program file ('" ~ args[programPos] ~ "').");
|
||||||
root = makeEvalFile(importWorld ~ "void main(char[][] args) {\n"
|
root = makeEvalFile(makeEvalCode(eval, No.loop));
|
||||||
~ std.string.join(eval, "\n") ~ ";\n}");
|
|
||||||
argsBeforeProgram ~= "-d";
|
argsBeforeProgram ~= "-d";
|
||||||
}
|
}
|
||||||
else if (programPos < args.length)
|
else if (programPos < args.length)
|
||||||
|
@ -839,6 +835,101 @@ import std.stdio, std.algorithm, std.array, std.ascii, std.base64,
|
||||||
std.zlib;
|
std.zlib;
|
||||||
";
|
";
|
||||||
|
|
||||||
|
/**
|
||||||
|
Joins together the code provided via an `--eval` or `--loop`
|
||||||
|
flag, ensuring a trailing `;` is added if not already provided
|
||||||
|
by the user
|
||||||
|
|
||||||
|
Params:
|
||||||
|
eval = array of strings generated by the `--eval`
|
||||||
|
or `--loop` rdmd flags
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string of code to be evaluated, corresponding to the
|
||||||
|
inner code of either the program or the loop
|
||||||
|
*/
|
||||||
|
string innerEvalCode(string[] eval)
|
||||||
|
{
|
||||||
|
import std.string : join, stripRight;
|
||||||
|
// assumeSafeAppend just to avoid unnecessary reallocation
|
||||||
|
string code = eval.join("\n").stripRight.assumeSafeAppend;
|
||||||
|
if (code.length > 0 && code[$ - 1] != ';')
|
||||||
|
code ~= ';';
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
assert(innerEvalCode([`writeln("Hello!")`]) == `writeln("Hello!");`);
|
||||||
|
assert(innerEvalCode([`writeln("Hello!");`]) == `writeln("Hello!");`);
|
||||||
|
|
||||||
|
// test with trailing whitespace
|
||||||
|
assert(innerEvalCode([`writeln("Hello!") `]) == `writeln("Hello!");`);
|
||||||
|
assert(innerEvalCode([`writeln("Hello!"); `]) == `writeln("Hello!");`);
|
||||||
|
|
||||||
|
// test with multiple entries
|
||||||
|
assert(innerEvalCode([`writeln("Hello!"); `, `writeln("You!") `])
|
||||||
|
== "writeln(\"Hello!\"); \nwriteln(\"You!\");");
|
||||||
|
assert(innerEvalCode([`writeln("Hello!"); `, `writeln("You!"); `])
|
||||||
|
== "writeln(\"Hello!\"); \nwriteln(\"You!\");");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Formats the code provided via `--eval` or `--loop` flags into a
|
||||||
|
string of complete program code that can be written to a file
|
||||||
|
and then compiled
|
||||||
|
|
||||||
|
Params:
|
||||||
|
eval = array of strings generated by the `--eval` or
|
||||||
|
`--loop` rdmd flags
|
||||||
|
loop = set to `Yes.loop` if this code comes from a
|
||||||
|
`--loop` flag, `No.loop` if it comes from an
|
||||||
|
`--eval` flag
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string of code to be evaluated, corresponding to the
|
||||||
|
inner code of either the program or the loop
|
||||||
|
*/
|
||||||
|
string makeEvalCode(string[] eval, Flag!"loop" loop)
|
||||||
|
{
|
||||||
|
import std.format : format;
|
||||||
|
immutable codeFormat = importWorld
|
||||||
|
~ "void main(char[][] args) {%s%s\n%s}";
|
||||||
|
|
||||||
|
immutable innerCodeOpening =
|
||||||
|
loop ? " foreach (line; std.stdio.stdin.byLine()) {\n"
|
||||||
|
: "\n";
|
||||||
|
|
||||||
|
immutable innerCodeClosing = loop ? "} " : "";
|
||||||
|
|
||||||
|
return format(codeFormat,
|
||||||
|
innerCodeOpening,
|
||||||
|
innerEvalCode(eval),
|
||||||
|
innerCodeClosing);
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
// innerEvalCode already tests the cases for different
|
||||||
|
// contents in `eval` array, so let's focus on testing
|
||||||
|
// the difference based on the `loop` flag
|
||||||
|
assert(makeEvalCode([`writeln("Hello!") `], No.loop) ==
|
||||||
|
importWorld
|
||||||
|
~ "void main(char[][] args) {\n"
|
||||||
|
~ "writeln(\"Hello!\");\n}");
|
||||||
|
|
||||||
|
assert(makeEvalCode([`writeln("What!"); `], No.loop) ==
|
||||||
|
importWorld
|
||||||
|
~ "void main(char[][] args) {\n"
|
||||||
|
~ "writeln(\"What!\");\n}");
|
||||||
|
|
||||||
|
assert(makeEvalCode([`writeln("Loop!") ; `], Yes.loop) ==
|
||||||
|
importWorld
|
||||||
|
~ "void main(char[][] args) { "
|
||||||
|
~ "foreach (line; std.stdio.stdin.byLine()) {\n"
|
||||||
|
~ "writeln(\"Loop!\") ;\n} }");
|
||||||
|
}
|
||||||
|
|
||||||
string makeEvalFile(string todo)
|
string makeEvalFile(string todo)
|
||||||
{
|
{
|
||||||
auto pathname = myOwnTmpDir;
|
auto pathname = myOwnTmpDir;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue