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,
|
||||
std.digest.md, std.exception, std.file, std.getopt,
|
||||
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)
|
||||
{
|
||||
|
@ -180,18 +180,14 @@ int main(string[] args)
|
|||
{
|
||||
enforce(programPos == args.length, "Cannot have both --loop and a " ~
|
||||
"program file ('" ~ args[programPos] ~ "').");
|
||||
root = makeEvalFile(importWorld ~ "void main(char[][] args) { "
|
||||
~ "foreach (line; std.stdio.stdin.byLine()) {\n"
|
||||
~ std.string.join(loop, "\n")
|
||||
~ ";\n} }");
|
||||
root = makeEvalFile(makeEvalCode(loop, Yes.loop));
|
||||
argsBeforeProgram ~= "-d";
|
||||
}
|
||||
else if (eval.ptr)
|
||||
{
|
||||
enforce(programPos == args.length, "Cannot have both --eval and a " ~
|
||||
"program file ('" ~ args[programPos] ~ "').");
|
||||
root = makeEvalFile(importWorld ~ "void main(char[][] args) {\n"
|
||||
~ std.string.join(eval, "\n") ~ ";\n}");
|
||||
root = makeEvalFile(makeEvalCode(eval, No.loop));
|
||||
argsBeforeProgram ~= "-d";
|
||||
}
|
||||
else if (programPos < args.length)
|
||||
|
@ -839,6 +835,101 @@ import std.stdio, std.algorithm, std.array, std.ascii, std.base64,
|
|||
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)
|
||||
{
|
||||
auto pathname = myOwnTmpDir;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue