Skip to content

Commit 30d7cff

Browse files
authored
Merge pull request #6385 from wilzbach/public-examples
Add more public examples to std.exception + enable DScanner check
2 parents 7d21b3e + 64ad4c2 commit 30d7cff

File tree

3 files changed

+119
-81
lines changed

3 files changed

+119
-81
lines changed

.dscanner.ini

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,6 @@ has_public_example="-etc.c.curl,\
228228
-std.datetime.systime,\
229229
-std.datetime.timezone,\
230230
-std.encoding,\
231-
-std.exception,\
232231
-std.experimental.allocator,\
233232
-std.experimental.allocator.building_blocks.allocator_list,\
234233
-std.experimental.allocator.building_blocks.bitmapped_block,\

posix.mak

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ ROOT_OF_THEM_ALL = generated
8282
ROOT = $(ROOT_OF_THEM_ALL)/$(OS)/$(BUILD)/$(MODEL)
8383
DUB=dub
8484
TOOLS_DIR=../tools
85-
DSCANNER_HASH=ef9853215d61731f1a4d97d13618e4cb12c40c57
85+
DSCANNER_HASH=0ef3df1fd63371d9680348a5a45efd8675321ffc
8686
DSCANNER_DIR=$(ROOT_OF_THEM_ALL)/dscanner-$(DSCANNER_HASH)
8787

8888
# Set DRUNTIME name and full path

std/exception.d

Lines changed: 118 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -725,7 +725,6 @@ deprecated
725725
assertThrown(enf(false, "blah"));
726726
}
727727

728-
729728
/++
730729
Catches and returns the exception thrown from the given expression.
731730
If no exception is thrown, then null is returned and $(D result) is
@@ -796,10 +795,11 @@ T collectException(T : Throwable = Exception, E)(lazy E expression)
796795
return null;
797796
}
798797

798+
///
799799
@safe unittest
800800
{
801801
int foo() { throw new Exception("blah"); }
802-
assert(collectException(foo()));
802+
assert(collectException(foo()).msg == "blah");
803803
}
804804

805805
/++
@@ -975,19 +975,24 @@ immutable(T[U]) assumeUnique(T, U)(ref T[U] array) pure nothrow
975975
return result;
976976
}
977977

978+
///
978979
@system unittest
979980
{
980-
// @system due to assumeUnique
981981
int[] arr = new int[1];
982-
auto arr1 = assumeUnique(arr);
983-
assert(is(typeof(arr1) == immutable(int)[]) && arr == null);
982+
auto arr1 = arr.assumeUnique;
983+
static assert(is(typeof(arr1) == immutable(int)[]));
984+
assert(arr == null);
985+
assert(arr1 == [0]);
984986
}
985987

988+
///
986989
@system unittest
987990
{
988991
int[string] arr = ["a":1];
989-
auto arr1 = assumeUnique(arr);
990-
assert(is(typeof(arr1) == immutable(int[string])) && arr == null);
992+
auto arr1 = arr.assumeUnique;
993+
static assert(is(typeof(arr1) == immutable(int[string])));
994+
assert(arr == null);
995+
assert(arr1.keys == ["a"]);
991996
}
992997

993998
/**
@@ -1582,25 +1587,28 @@ class ErrnoException : Exception
15821587
_errno = errno;
15831588
super(msg ~ " (" ~ errnoString(errno) ~ ")", file, line);
15841589
}
1590+
}
15851591

1586-
@system unittest
1587-
{
1588-
import core.stdc.errno : errno, EAGAIN;
1592+
///
1593+
@system unittest
1594+
{
1595+
import core.stdc.errno : EAGAIN;
1596+
auto ex = new ErrnoException("oh no", EAGAIN);
1597+
assert(ex.errno == EAGAIN);
1598+
}
15891599

1590-
auto old = errno;
1591-
scope(exit) errno = old;
1600+
/// errno is used by default if no explicit error code is provided
1601+
@system unittest
1602+
{
1603+
import core.stdc.errno : errno, EAGAIN;
15921604

1593-
errno = EAGAIN;
1594-
auto ex = new ErrnoException("oh no");
1595-
assert(ex.errno == EAGAIN);
1596-
}
1605+
auto old = errno;
1606+
scope(exit) errno = old;
15971607

1598-
@system unittest
1599-
{
1600-
import core.stdc.errno : EAGAIN;
1601-
auto ex = new ErrnoException("oh no", EAGAIN);
1602-
assert(ex.errno == EAGAIN);
1603-
}
1608+
// fake that errno got set by the callee
1609+
errno = EAGAIN;
1610+
auto ex = new ErrnoException("oh no");
1611+
assert(ex.errno == EAGAIN);
16041612
}
16051613

16061614
/++
@@ -1619,63 +1627,7 @@ class ErrnoException : Exception
16191627
Returns:
16201628
expression, if it does not throw. Otherwise, returns the result of
16211629
errorHandler.
1622-
1623-
Example:
1624-
$(RUNNABLE_EXAMPLE
1625-
--------------------
1626-
//Revert to a default value upon an error:
1627-
assert("x".to!int().ifThrown(0) == 0);
1628-
--------------------
1629-
)
1630-
1631-
You can also chain multiple calls to ifThrown, each capturing errors from the
1632-
entire preceding expression.
1633-
1634-
Example:
1635-
$(RUNNABLE_EXAMPLE
1636-
--------------------
1637-
//Chaining multiple calls to ifThrown to attempt multiple things in a row:
1638-
string s="true";
1639-
assert(s.to!int().
1640-
ifThrown(cast(int) s.to!double()).
1641-
ifThrown(cast(int) s.to!bool())
1642-
== 1);
1643-
1644-
//Respond differently to different types of errors
1645-
assert(enforce("x".to!int() < 1).to!string()
1646-
.ifThrown!ConvException("not a number")
1647-
.ifThrown!Exception("number too small")
1648-
== "not a number");
1649-
--------------------
1650-
)
1651-
1652-
The expression and the errorHandler must have a common type they can both
1653-
be implicitly casted to, and that type will be the type of the compound
1654-
expression.
1655-
1656-
Example:
1657-
$(RUNNABLE_EXAMPLE
1658-
--------------------
1659-
//null and new Object have a common type(Object).
1660-
static assert(is(typeof(null.ifThrown(new Object())) == Object));
1661-
static assert(is(typeof((new Object()).ifThrown(null)) == Object));
1662-
1663-
//1 and new Object do not have a common type.
1664-
static assert(!__traits(compiles, 1.ifThrown(new Object())));
1665-
static assert(!__traits(compiles, (new Object()).ifThrown(1)));
1666-
--------------------
1667-
)
1668-
1669-
If you need to use the actual thrown exception, you can use a delegate.
1670-
Example:
1671-
1672-
$(RUNNABLE_EXAMPLE
1673-
--------------------
1674-
//Use a lambda to get the thrown object.
1675-
assert("%s".format().ifThrown!Exception(e => e.classinfo.name) == "std.format.FormatException");
1676-
--------------------
1677-
)
1678-
+/
1630+
+/
16791631
//lazy version
16801632
CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, T2)(lazy scope T1 expression, lazy scope T2 errorHandler)
16811633
{
@@ -1738,6 +1690,59 @@ CommonType!(T1, T2) ifThrown(T1, T2)(lazy scope T1 expression, scope T2 delegate
17381690
}
17391691
}
17401692

1693+
/// Revert to a default value upon an error:
1694+
@safe unittest
1695+
{
1696+
import std.conv : to;
1697+
assert("x".to!int.ifThrown(0) == 0);
1698+
}
1699+
1700+
/**
1701+
Chain multiple calls to ifThrown, each capturing errors from the
1702+
entire preceding expression.
1703+
*/
1704+
@safe unittest
1705+
{
1706+
import std.conv : ConvException, to;
1707+
string s = "true";
1708+
assert(s.to!int.ifThrown(cast(int) s.to!double)
1709+
.ifThrown(cast(int) s.to!bool) == 1);
1710+
1711+
s = "2.0";
1712+
assert(s.to!int.ifThrown(cast(int) s.to!double)
1713+
.ifThrown(cast(int) s.to!bool) == 2);
1714+
1715+
// Respond differently to different types of errors
1716+
alias orFallback = (lazy a) => a.ifThrown!ConvException("not a number")
1717+
.ifThrown!Exception("number too small");
1718+
1719+
assert(orFallback(enforce("x".to!int < 1).to!string) == "not a number");
1720+
assert(orFallback(enforce("2".to!int < 1).to!string) == "number too small");
1721+
}
1722+
1723+
/**
1724+
The expression and the errorHandler must have a common type they can both
1725+
be implicitly casted to, and that type will be the type of the compound
1726+
expression.
1727+
*/
1728+
@safe unittest
1729+
{
1730+
// null and new Object have a common type(Object).
1731+
static assert(is(typeof(null.ifThrown(new Object())) == Object));
1732+
static assert(is(typeof((new Object()).ifThrown(null)) == Object));
1733+
1734+
// 1 and new Object do not have a common type.
1735+
static assert(!__traits(compiles, 1.ifThrown(new Object())));
1736+
static assert(!__traits(compiles, (new Object()).ifThrown(1)));
1737+
}
1738+
1739+
/// Use a lambda to get the thrown object.
1740+
@system unittest
1741+
{
1742+
import std.format : format;
1743+
assert("%s".format.ifThrown!Exception(e => e.classinfo.name) == "std.format.FormatException");
1744+
}
1745+
17411746
//Verify Examples
17421747
@system unittest
17431748
{
@@ -1841,6 +1846,40 @@ enum RangePrimitive
18411846
pop = popFront | popBack, /// Ditto
18421847
}
18431848

1849+
///
1850+
pure @safe unittest
1851+
{
1852+
import std.algorithm.comparison : equal;
1853+
import std.algorithm.iteration : map, splitter;
1854+
import std.conv : to, ConvException;
1855+
1856+
auto s = "12,1337z32,54,2,7,9,1z,6,8";
1857+
1858+
// The next line composition will throw when iterated
1859+
// as some elements of the input do not convert to integer
1860+
auto r = s.splitter(',').map!(a => to!int(a));
1861+
1862+
// Substitute 0 for cases of ConvException
1863+
auto h = r.handle!(ConvException, RangePrimitive.front, (e, r) => 0);
1864+
assert(h.equal([12, 0, 54, 2, 7, 9, 0, 6, 8]));
1865+
}
1866+
1867+
///
1868+
pure @safe unittest
1869+
{
1870+
import std.algorithm.comparison : equal;
1871+
import std.range : retro;
1872+
import std.utf : UTFException;
1873+
1874+
auto str = "hello\xFFworld"; // 0xFF is an invalid UTF-8 code unit
1875+
1876+
auto handled = str.handle!(UTFException, RangePrimitive.access,
1877+
(e, r) => ' '); // Replace invalid code points with spaces
1878+
1879+
assert(handled.equal("hello world")); // `front` is handled,
1880+
assert(handled.retro.equal("dlrow olleh")); // as well as `back`
1881+
}
1882+
18441883
/** Handle exceptions thrown from range primitives.
18451884
18461885
Use the $(LREF RangePrimitive) enum to specify which primitives to _handle.

0 commit comments

Comments
 (0)