├── runkoans.sh ├── .github └── FUNDING.yml ├── .gitignore ├── scripts ├── runner_linux.sh └── runner_osx.sh ├── koans ├── pointers.d ├── helpers.d ├── enums.d ├── unions.d ├── templates.d ├── ref_functions.d ├── bitwise_operators.d ├── properties.d ├── package.d ├── traits.d ├── basics.d ├── structs.d ├── files.d ├── chars.d ├── numbers.d ├── operator_overloading.d ├── c_interop.d ├── ctfe.d ├── alias_this.d ├── mixins.d ├── foreach_loop.d ├── exceptions.d ├── tuples.d ├── strings.d ├── concurrency.d ├── lambda_syntax.d ├── associative_arrays.d ├── function_parameters.d ├── classes.d ├── arrays.d └── delegates.d ├── dub.json ├── README.md ├── learn.d └── dscanner.ini /runkoans.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | dub --build=unittest -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: ilmanzo 2 | open_collective: andrea-manzini 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.obj 3 | obj/ 4 | .dub/ 5 | dub.selections.json 6 | bin/dub 7 | dlang_koans 8 | dlang_koans-test-library 9 | dlang_koans-test-application 10 | -------------------------------------------------------------------------------- /scripts/runner_linux.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #sudo apt-get install inotify-tools 3 | while true; do 4 | inotifywait -e close_write,moved_to,create source 5 | dub --build=unittest 6 | done 7 | -------------------------------------------------------------------------------- /koans/pointers.d: -------------------------------------------------------------------------------- 1 | module koans.pointers; 2 | 3 | import koans.helpers; 4 | 5 | unittest // pointerDereference() 6 | { 7 | int a = 3; 8 | int* p = &a; 9 | *p = 4; 10 | assert(a == FILL_IN_THIS_NUMBER); 11 | } 12 | -------------------------------------------------------------------------------- /scripts/runner_osx.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This requires fswatch to be installed. 4 | # If you are using homebrew, just `brew install fswatch`. 5 | 6 | while true; do 7 | fswatch -1 -e .git . 8 | dub --build=unittest 9 | done 10 | -------------------------------------------------------------------------------- /koans/helpers.d: -------------------------------------------------------------------------------- 1 | module koans.helpers; 2 | 3 | public static immutable FILL_IN_THIS_CHAR = ' '; 4 | public static immutable FILL_IN_THIS_NUMBER = 42; 5 | public static immutable FILL_IN_THIS_STRING = "__a random string__"; 6 | public static immutable FILL_IN_THIS_DECIMAL = 3.141592; 7 | public static immutable FILL_IN_TRUE_OR_FALSE = false; 8 | public static immutable FILL_IN_THIS_ARRAY = [42, 42, 42, 42, 42]; 9 | -------------------------------------------------------------------------------- /koans/enums.d: -------------------------------------------------------------------------------- 1 | module koans.enums; 2 | 3 | import koans.helpers; 4 | 5 | enum Color 6 | { 7 | RED = 1, 8 | GREEN, 9 | BLUE 10 | } 11 | 12 | unittest // enums_have_properties() 13 | { 14 | assert(Color.init == FILL_IN_THIS_NUMBER); 15 | assert(Color.min == FILL_IN_THIS_NUMBER); 16 | assert(Color.max == FILL_IN_THIS_NUMBER); 17 | assert(Color.sizeof == FILL_IN_THIS_NUMBER); 18 | } 19 | -------------------------------------------------------------------------------- /dub.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "Andrea Manzini" 4 | ], 5 | "importPaths": [ 6 | "koans" 7 | ], 8 | "sourcePaths": ["."], 9 | "copyright": "Copyright © Andrea Manzini", 10 | "description": "A series of exercises to learn D Programming Language", 11 | "homepage": "https://github.com/ilmanzo/DLangKoans", 12 | "license": "GPL-2.0", 13 | "name": "dlang_koans", 14 | "targetType": "executable", 15 | "mainSourceFile": "learn.d" 16 | } 17 | -------------------------------------------------------------------------------- /koans/unions.d: -------------------------------------------------------------------------------- 1 | module koans.unions; 2 | 3 | import koans.helpers; 4 | 5 | //union definition 6 | union IpAddressV4 7 | { 8 | ubyte[4] bytes; 9 | uint value; 10 | } 11 | 12 | unittest // union_size() 13 | { 14 | const auto sz = IpAddressV4.sizeof; 15 | assert(sz == FILL_IN_THIS_NUMBER); 16 | } 17 | 18 | unittest // union_assignment() 19 | { 20 | const auto ip = IpAddressV4([127, 0, 0, 1]); 21 | assert(ip.value == FILL_IN_THIS_NUMBER); 22 | } 23 | -------------------------------------------------------------------------------- /koans/templates.d: -------------------------------------------------------------------------------- 1 | module koans.templates; 2 | 3 | import koans.helpers; 4 | 5 | T twice(T)(T value) 6 | { //shortcut syntax 7 | return 2 * value; 8 | } 9 | 10 | T twice(T : string)(T value) 11 | { // specialization 12 | return value ~ value; 13 | } 14 | 15 | unittest // functionTemplates() 16 | { 17 | auto val1 = twice!int(2); // instantiation 18 | assert(val1 == FILL_IN_THIS_NUMBER); 19 | auto val2 = twice("hello"); 20 | assert(val2 == FILL_IN_THIS_STRING); 21 | } 22 | -------------------------------------------------------------------------------- /koans/ref_functions.d: -------------------------------------------------------------------------------- 1 | module koans.ref_functions; 2 | 3 | import koans.helpers; 4 | 5 | // A ref function returns by reference (instead of by value). The return value of a ref function must be an lvalue 6 | 7 | unittest 8 | { 9 | int* p; 10 | 11 | ref int foo() 12 | { 13 | p = new int(2); 14 | return *p; 15 | } 16 | 17 | int i = foo(); 18 | assert(i == FILL_IN_THIS_NUMBER); 19 | 20 | foo() = 3; // reference returns can be lvalues 21 | assert(*p == FILL_IN_THIS_NUMBER); 22 | } 23 | -------------------------------------------------------------------------------- /koans/bitwise_operators.d: -------------------------------------------------------------------------------- 1 | module koans.bitwise_operators; 2 | 3 | import koans.helpers; 4 | 5 | unittest // shifts() 6 | { 7 | auto i = 1; 8 | auto j = -8; 9 | assert(j << 3 == FILL_IN_THIS_NUMBER); 10 | assert(j >>> 3 == FILL_IN_THIS_NUMBER); 11 | assert(j >> 3 == FILL_IN_THIS_NUMBER); 12 | assert(i << 3 == FILL_IN_THIS_NUMBER); 13 | } 14 | 15 | unittest // operators() 16 | { 17 | assert((2 | 4) == FILL_IN_THIS_NUMBER); // or 18 | assert((3 & 5) == FILL_IN_THIS_NUMBER); // and 19 | assert((6 ^ 4) == FILL_IN_THIS_NUMBER); // xor 20 | assert((~3) == FILL_IN_THIS_NUMBER); // not 21 | } 22 | -------------------------------------------------------------------------------- /koans/properties.d: -------------------------------------------------------------------------------- 1 | module koans.properties; 2 | 3 | import koans.helpers; 4 | 5 | unittest // nativeProperties() 6 | { 7 | auto x = 3; 8 | assert(x.sizeof == FILL_IN_THIS_NUMBER); 9 | assert(typeof(x).stringof == FILL_IN_THIS_STRING); 10 | } 11 | 12 | unittest // userDefinedProperties() 13 | { 14 | struct Rectangle 15 | { 16 | int width; 17 | int height; 18 | @property auto area() 19 | { 20 | return width * height; 21 | } 22 | } 23 | 24 | Rectangle r; 25 | r.width = 4; 26 | r.height = 3; 27 | assert(r.area == FILL_IN_THIS_NUMBER); 28 | } 29 | -------------------------------------------------------------------------------- /koans/package.d: -------------------------------------------------------------------------------- 1 | module koans; 2 | 3 | // to test only one module 4 | // static immutable koansModules = ["ref_functions"]; 5 | 6 | static immutable koansModules = [ 7 | "basics", "numbers", "chars", "strings", 8 | "bitwise_operators", "enums", "arrays", 9 | "associative_arrays", "foreach_loop", 10 | "structs", "unions", "function_parameters", 11 | "classes", "properties", "pointers", 12 | "ref_functions", " exceptions", "ctfe", "files", 13 | "templates", "mixins", "tuples", "traits", 14 | "delegates", "c_interop", "alias_this", 15 | "operator_overloading", "lambda_syntax", 16 | "concurrency", 17 | ]; 18 | 19 | 20 | static foreach (m; koansModules) 21 | mixin("public static import koans." ~ m ~ ";"); 22 | -------------------------------------------------------------------------------- /koans/traits.d: -------------------------------------------------------------------------------- 1 | module koans.traits; 2 | 3 | import koans.helpers; 4 | 5 | /* 6 | * Traits are extensions to the language to enable programs, at compile time, 7 | * to get at information internal to the compiler. This is also known as compile time reflection. 8 | */ 9 | 10 | class MyClass 11 | { 12 | this() 13 | { 14 | } 15 | 16 | ~this() 17 | { 18 | } 19 | 20 | void foo() 21 | { 22 | } 23 | 24 | int foo(int) 25 | { 26 | return 0; 27 | } 28 | } 29 | 30 | unittest // allMembers() 31 | { 32 | auto members = [__traits(allMembers, MyClass)]; 33 | assert(members.length == FILL_IN_THIS_NUMBER); 34 | import std.algorithm : canFind; 35 | 36 | assert(members.canFind("foo") == FILL_IN_TRUE_OR_FALSE); 37 | } 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DLangKoans 2 | ========== 3 | 4 | The D Programming Language Koans. Inspired from RubyKoans, CppKoans, GoKoans; an educational unit test suite for the [D Programming Language](https://dlang.org) 5 | 6 | ...work in progress... 7 | 8 | SETUP: 9 | ------ 10 | - clone or download this repository 11 | - install dub build manager https://code.dlang.org/download 12 | - enjoy 13 | 14 | 15 | How it works: 16 | ------------ 17 | - execute `dub --build=unittest` 18 | - observe test errors 19 | - think and make the test pass 20 | - goto first step 21 | 22 | 23 | References: 24 | ----------- 25 | - The original! http://rubykoans.com 26 | - https://github.com/torbjoernk/CppKoans/ 27 | - https://github.com/cdarwin/go-koans 28 | 29 | Thanks to: 30 | ----------- 31 | [Ali Çehreli - Programming in D](http://ddili.org/ders/d.en/index.html) 32 | -------------------------------------------------------------------------------- /koans/basics.d: -------------------------------------------------------------------------------- 1 | module koans.basics; 2 | 3 | import koans.helpers; 4 | 5 | import std.math; // for isNaN 6 | 7 | struct My_struct 8 | { 9 | int x; 10 | float f; 11 | string s; 12 | } 13 | 14 | unittest 15 | { 16 | assert(true == FILL_IN_TRUE_OR_FALSE); 17 | assert(5 % 2 == FILL_IN_THIS_NUMBER); 18 | assert(5 * 2 == FILL_IN_THIS_NUMBER); 19 | assert((5 ^ 2) == FILL_IN_THIS_NUMBER); 20 | 21 | //zero values 22 | int x; 23 | assert(x == FILL_IN_THIS_NUMBER); 24 | 25 | //for all types 26 | float f; 27 | assert(isNaN(f) == FILL_IN_TRUE_OR_FALSE); // float equality is not defined, e.g. nan != nan 28 | 29 | My_struct c; //also composite gets default initializers 30 | 31 | assert(c.x == FILL_IN_THIS_NUMBER); 32 | assert(isNaN(c.f) == FILL_IN_TRUE_OR_FALSE); 33 | assert(c.s == FILL_IN_THIS_STRING); 34 | } 35 | -------------------------------------------------------------------------------- /koans/structs.d: -------------------------------------------------------------------------------- 1 | module koans.structs; 2 | 3 | import koans.helpers; 4 | 5 | //struct defines a type, not a variable 6 | struct TimeOfDay 7 | { 8 | int hour; 9 | int minute; 10 | } 11 | 12 | struct Student 13 | { 14 | int number; 15 | int[] grades; 16 | } 17 | 18 | unittest // structs_can_be_initialized() 19 | { 20 | auto t1 = TimeOfDay(8, 30); // preferred syntax 21 | assert(t1.minute == FILL_IN_THIS_NUMBER); 22 | TimeOfDay t2 = {9, 45}; // alternate C syntax 23 | assert(t2.hour == FILL_IN_THIS_NUMBER); 24 | auto t3 = TimeOfDay(10); // not all members need to be specified 25 | assert(t3.minute == FILL_IN_THIS_NUMBER); 26 | } 27 | 28 | unittest // structs_members_are_copied() 29 | { 30 | auto student1 = Student(1, [70, 90, 85]); 31 | auto student2 = student1; 32 | student2.number = 2; 33 | assert(student2.grades == FILL_IN_THIS_ARRAY); 34 | } 35 | -------------------------------------------------------------------------------- /koans/files.d: -------------------------------------------------------------------------------- 1 | module koans.files; 2 | 3 | import koans.helpers; 4 | 5 | // fill in the value replacing the underscore 6 | 7 | immutable auto FILENAME = "just_a_test.txt"; 8 | 9 | void createTestFile() 10 | { 11 | import std.stdio : File; //notice the local import 12 | auto testfile = File(FILENAME, "w"); 13 | testfile.writeln("some data"); 14 | } //file is closed when File object goes out of scope 15 | 16 | void removeTestFile() 17 | { 18 | import std.file : remove; //notice the local import 19 | remove(FILENAME); 20 | } //file is closed when File object goes out of scope 21 | 22 | unittest // readFile() 23 | { 24 | import std.stdio : File; 25 | import std.string : strip; 26 | 27 | createTestFile; 28 | auto myfile = File(FILENAME, "r"); 29 | auto data = strip(myfile.readln()); 30 | auto expected = FILL_IN_THIS_STRING; 31 | assert(expected, data); 32 | removeTestFile; 33 | } 34 | -------------------------------------------------------------------------------- /koans/chars.d: -------------------------------------------------------------------------------- 1 | module koans.chars; 2 | 3 | import koans.helpers; 4 | 5 | unittest // lonely_char() 6 | { 7 | char a_character = 'a'; 8 | assert(a_character == FILL_IN_THIS_CHAR); 9 | //assert(a_character == 'b'); 10 | } 11 | 12 | unittest // chars_have_a_size() 13 | { 14 | char a_character = 'b'; 15 | assert(a_character.sizeof == 3, "chars have a size"); 16 | } 17 | 18 | unittest // chars_are_numbers() 19 | { 20 | char a_character = 'A'; 21 | assert(cast(int)(a_character) == FILL_IN_THIS_NUMBER); 22 | } 23 | 24 | unittest // more_chars_are_a_string() 25 | { 26 | string some_characters = "Hello World"; 27 | assert(some_characters.length == FILL_IN_THIS_NUMBER); 28 | } 29 | 30 | unittest // unicode_chars() 31 | { 32 | char e1 = 'e'; 33 | wchar e2 = 'è'; 34 | dchar e3 = 'é'; 35 | assert(e1.sizeof == FILL_IN_THIS_NUMBER); 36 | assert(e2.sizeof == FILL_IN_THIS_NUMBER); 37 | assert(e3.sizeof == FILL_IN_THIS_NUMBER); 38 | } 39 | -------------------------------------------------------------------------------- /koans/numbers.d: -------------------------------------------------------------------------------- 1 | module koans.numbers; 2 | 3 | import koans.helpers; 4 | 5 | // fill in the value replacing the underscore 6 | 7 | unittest 8 | { 9 | auto integer = 1; 10 | auto expected = FILL_IN_THIS_NUMBER; 11 | assert(expected == integer); 12 | } 13 | 14 | unittest 15 | { 16 | int an_integer = 1; 17 | assert(int.sizeof == FILL_IN_THIS_NUMBER); 18 | assert(an_integer.sizeof == FILL_IN_THIS_NUMBER); 19 | } 20 | 21 | // hint: here you may want to change assert condition 22 | unittest 23 | { 24 | int an_integer = -42; 25 | assert(an_integer == 0); 26 | } 27 | 28 | unittest 29 | { 30 | int my_integer = 36; 31 | assert(my_integer.init == FILL_IN_THIS_NUMBER); // initial value 32 | assert(my_integer.stringof == FILL_IN_THIS_STRING); // string representation 33 | } 34 | 35 | unittest 36 | { 37 | uint binNumber = 0b_10000000_00000000_00000000_00000000; 38 | uint hexNumber = 0x_0030_a00f; 39 | assert(binNumber == FILL_IN_THIS_NUMBER); 40 | assert(hexNumber == FILL_IN_THIS_NUMBER); 41 | } 42 | -------------------------------------------------------------------------------- /koans/operator_overloading.d: -------------------------------------------------------------------------------- 1 | module koans.operator_overloading; 2 | 3 | import koans.helpers; 4 | 5 | //Operator overloading is accomplished by rewriting operators 6 | // whose operands are class or struct objects into calls to specially named member functions. 7 | //No additional syntax is used. 8 | 9 | struct Color 10 | { 11 | ubyte r, g, b; 12 | bool opEquals(Color col) const 13 | { 14 | return (this.r == col.r) && (this.g == col.g) && (this.b == col.b); 15 | } 16 | 17 | size_t toHash() const nothrow @safe 18 | { 19 | return r * 256 * 256 + g * 256 + b; 20 | } 21 | } 22 | 23 | unittest // colorEquality() 24 | { 25 | const Color green1 = {r: 0, g: 200, b: 0}; 26 | const Color red = {r: 200, g: 0, b: 0}; 27 | const Color green2 = {r: 0, g: 200, b: 0}; 28 | auto result1 = (green1 == green2); 29 | auto result2 = (green1 == red); 30 | assert(result1 == FILL_IN_TRUE_OR_FALSE); 31 | assert(result2 == FILL_IN_TRUE_OR_FALSE); 32 | } 33 | 34 | //TODO show off other operator overloading 35 | -------------------------------------------------------------------------------- /koans/c_interop.d: -------------------------------------------------------------------------------- 1 | module koans.c_interop; 2 | 3 | import koans.helpers; 4 | 5 | extern (C) 6 | { 7 | int simple_c_function(int a, int b) 8 | { 9 | return a + b + 42; 10 | } 11 | 12 | void pointers_c_function(int* n) 13 | { 14 | *n += 3; 15 | } 16 | 17 | char string_c_function(const char* str) 18 | { 19 | return str[3]; 20 | } 21 | } 22 | 23 | unittest // callSimpleCfunction() 24 | { 25 | assert(simple_c_function(10, 20) == FILL_IN_THIS_NUMBER); 26 | } 27 | 28 | unittest // pointers_are_interoperable() 29 | { 30 | auto x = 5; 31 | pointers_c_function(&x); 32 | assert(x == FILL_IN_THIS_NUMBER); 33 | } 34 | 35 | unittest // working_with_c_strings() 36 | { 37 | //string literals are fine 38 | assert(string_c_function("This is a test") == FILL_IN_THIS_CHAR); 39 | // variables needs to be converted 40 | auto message = "Just another test"; 41 | import std.string : toStringz; 42 | 43 | auto result = string_c_function(toStringz(message)); 44 | assert(result == FILL_IN_THIS_CHAR); 45 | } 46 | -------------------------------------------------------------------------------- /koans/ctfe.d: -------------------------------------------------------------------------------- 1 | module koans.ctfe; 2 | 3 | import koans.helpers; 4 | 5 | /* CTFE stands for Compile Time Function Execution; 6 | * D compiler is able to execute code at compile time 7 | */ 8 | 9 | size_t counter; 10 | 11 | int sum(int x, int y) 12 | { 13 | return x + y; 14 | } 15 | 16 | int factorial(int x) 17 | { // a classic 18 | int result = 1; 19 | for (auto i = 2; i <= x; i++) 20 | { 21 | result = result * i; 22 | } 23 | if (!__ctfe) 24 | { 25 | // This code is for execution at run time 26 | ++counter; 27 | } 28 | return result; 29 | } 30 | 31 | unittest // simple_CTFE() 32 | { 33 | auto a = 1 + 2; // this expression is evaluated by the compiler (like in C) 34 | enum b = sum(3, 4); // but also this. What's the difference ? 35 | assert(a == FILL_IN_THIS_NUMBER); 36 | assert(b == FILL_IN_THIS_NUMBER); 37 | } 38 | 39 | unittest // advanced_CTFE() 40 | { 41 | auto x = factorial(2); 42 | enum y = factorial(3); 43 | assert(x + y == FILL_IN_THIS_NUMBER); 44 | assert(counter == FILL_IN_THIS_NUMBER); 45 | } 46 | -------------------------------------------------------------------------------- /koans/alias_this.d: -------------------------------------------------------------------------------- 1 | //use this empty template as a start for writing new 'about' entries 2 | module koans.alias_this; 3 | 4 | import koans.helpers; 5 | 6 | /* 'alias this' enables automatic type conversions 7 | (also known as implicit type conversions) 8 | of user-defined types. 9 | The value of the member becomes the resulting value of the 10 | conversion. */ 11 | 12 | struct A 13 | { 14 | string name; 15 | int n; 16 | alias n this; 17 | } 18 | 19 | struct B 20 | { 21 | int foo() 22 | { 23 | return 1; 24 | } 25 | 26 | alias foo this; 27 | } 28 | 29 | int sum(int a, int b) // function sum() takes 2 int .. 30 | { 31 | return a + b; 32 | } 33 | 34 | unittest // type_conversion() 35 | { 36 | A a = {name: "the A struct", n: 11}; 37 | B b; 38 | auto result = sum(a, b); // but we can pass our struct 39 | assert(result == FILL_IN_THIS_NUMBER); 40 | } 41 | 42 | unittest // assignment() 43 | { 44 | A a = {name: "another A struct", n: 11}; 45 | a.n = 19; // think what does this ... Is it legal ? Why ? 46 | assert(a == FILL_IN_THIS_NUMBER); 47 | } 48 | -------------------------------------------------------------------------------- /koans/mixins.d: -------------------------------------------------------------------------------- 1 | module koans.mixins; 2 | 3 | import koans.helpers; 4 | 5 | int helper(int a, int b) 6 | { 7 | return a * 2 + b * 2; 8 | } 9 | 10 | /* from the DLang tour: 11 | The mixin expression takes an arbitrary string and compiles it and generates instructions accordingly. 12 | It is purely a compile-time mechanism and can only work on strings available during compilation - 13 | a comparison with the evil JavaScript eval would be highly unfair. 14 | */ 15 | 16 | unittest // first_very_simple_mixin() 17 | { 18 | auto n = mixin("3+2"); 19 | assert(n == FILL_IN_THIS_NUMBER); 20 | } 21 | 22 | unittest // another_simple_mixin() 23 | { 24 | const part1 = "int n=he"; 25 | const part2 = "lper(3,2);"; 26 | mixin(part1 ~ part2); 27 | assert(n == FILL_IN_THIS_NUMBER); // where n came from ? 28 | } 29 | 30 | unittest // a_more_interesting_mixin() 31 | { 32 | 33 | auto calc(string op, T)(T lhs, T rhs) 34 | { 35 | return mixin("lhs " ~ op ~ " rhs"); 36 | } 37 | 38 | auto n = calc!"+"(2, 2); 39 | assert(n == FILL_IN_THIS_NUMBER); // templatized mixin, why not ? 40 | 41 | } 42 | -------------------------------------------------------------------------------- /learn.d: -------------------------------------------------------------------------------- 1 | module learn; 2 | 3 | import core.runtime; 4 | import std.stdio; 5 | import koans; 6 | static import core.exception; 7 | 8 | shared static this() 9 | { 10 | // Override the default unit test runner to do nothing. 11 | // After that, "main" will be called. 12 | Runtime.moduleUnitTester = { return true; }; 13 | } 14 | 15 | void main() 16 | { 17 | writeln("Starting your journey to enlightenment..."); 18 | writeln("You will be asked to fill in the blanks in the koans."); 19 | writeln("Ensure to run 'dub --build=unittest' to run the tests."); 20 | static foreach (m; koans.koansModules) 21 | { 22 | mixin("static import koans." ~ m ~ ";"); 23 | foreach (t; __traits(getUnitTests, mixin("koans." ~ m))) 24 | { 25 | try 26 | { 27 | t(); 28 | } 29 | catch (core.exception.AssertError e) 30 | { 31 | writeln("Meditate more on ", e.file, " at line ", e.line); 32 | return; 33 | } 34 | } 35 | } 36 | writeln("You have reached the end of your journey"); 37 | } 38 | -------------------------------------------------------------------------------- /koans/foreach_loop.d: -------------------------------------------------------------------------------- 1 | module koans.foreach_loop; 2 | 3 | import koans.helpers; 4 | 5 | unittest // arrays_iteration() 6 | { 7 | auto array = [3, 4, 5, 6]; 8 | 9 | foreach (x; array) 10 | { // simple iteration, what is the scope of 'x'? 11 | x = x * 2; 12 | } 13 | assert(array[0] == FILL_IN_THIS_NUMBER); 14 | 15 | foreach (ref x; array) 16 | { // what is changed ? 17 | x = x * 2; 18 | } 19 | assert(array[0] == FILL_IN_THIS_NUMBER); 20 | } 21 | 22 | unittest // strings_iteration() 23 | { // in D, string are immutable arrays of chars 24 | char k; 25 | 26 | foreach (c; "this is a short string") 27 | { 28 | k = c; 29 | } 30 | 31 | assert(k == FILL_IN_THIS_CHAR); 32 | } 33 | 34 | unittest // foreach_with_associative_arrays() 35 | { 36 | int[string] aa; 37 | string s; 38 | int v; 39 | 40 | aa["Torvalds"] = 1969; 41 | aa["Stallman"] = 1953; 42 | aa["Kernighan"] = 1942; 43 | aa["Ritchie"] = 1941; 44 | 45 | foreach (key, value; aa) 46 | { 47 | s ~= key[0]; 48 | v += value - 1900; 49 | } 50 | 51 | assert(s == FILL_IN_THIS_STRING); 52 | assert(v == FILL_IN_THIS_NUMBER); 53 | } 54 | -------------------------------------------------------------------------------- /koans/exceptions.d: -------------------------------------------------------------------------------- 1 | module koans.exceptions; 2 | 3 | import koans.helpers; 4 | 5 | private class Bad_area : Exception 6 | { 7 | public this(string msg) 8 | { 9 | super(msg); 10 | } 11 | } 12 | 13 | private class Something_else : Exception 14 | { 15 | public this(string msg) 16 | { 17 | super(msg); 18 | } 19 | } 20 | 21 | private int area(int length, int width) 22 | { 23 | if (length <= 0 || width <= 0) 24 | throw new Bad_area("bad area!"); 25 | if (length == 4 || width == 0) 26 | throw new Something_else("Something else!"); 27 | return length * width; 28 | } 29 | 30 | unittest // aboutThrowingSomething() 31 | { 32 | auto result = 0; 33 | auto area1 = 0; 34 | try 35 | { 36 | area1 = area(4, 2); 37 | } 38 | catch (Bad_area be) 39 | { 40 | result = 1; 41 | } 42 | catch (Exception e) 43 | { 44 | result = 2; 45 | } 46 | 47 | assert(area1 == FILL_IN_THIS_NUMBER); 48 | assert(result == FILL_IN_THIS_NUMBER); 49 | } 50 | 51 | // unittest // aboutEnforce() 52 | // { 53 | // import std.exception : enforce; 54 | 55 | // auto exception = expectThrows(enforce(false)); 56 | // assert(exception.msg == FILL_IN_THIS_STRING); 57 | // } 58 | -------------------------------------------------------------------------------- /koans/tuples.d: -------------------------------------------------------------------------------- 1 | module koans.tuples; 2 | 3 | import koans.helpers; 4 | 5 | // Tuples are for combining multiple values to be used as a single object. They are like structs but easier to use. 6 | 7 | // relevant chapter from the online book: http://ddili.org/ders/d.en/tuples.html 8 | 9 | import std.typecons; 10 | 11 | unittest // construct_tuple_simple() 12 | { 13 | auto mytuple = tuple(13, "bananas"); 14 | assert(mytuple[0] == FILL_IN_THIS_NUMBER); // tuples element can be accessed by index 15 | assert(mytuple[1] == FILL_IN_THIS_STRING); // also iteration works here 16 | } 17 | 18 | unittest // construct_tuple_template() 19 | { 20 | // if you build the tuple using the template Tuple!() you can access elements by name 21 | auto mytuple = Tuple!(int, "number", string, "fruitname")(13, "bananas"); 22 | assert(mytuple.fruitname == FILL_IN_THIS_STRING); // tuples element can also be accessed by name 23 | } 24 | 25 | unittest // expand or slicing a tuple converts it in a list of objects. THIS IS DONE AT COMPILE TIME! 26 | { 27 | auto coords = Tuple!(float, "x", float, "y", float, "z")(1.5, 2.6, 3.4); 28 | auto array = [coords.expand, coords[]]; //array of floats declaration and initialization 29 | assert(array.length == FILL_IN_THIS_NUMBER); 30 | } 31 | -------------------------------------------------------------------------------- /koans/strings.d: -------------------------------------------------------------------------------- 1 | module koans.strings; 2 | 3 | import koans.helpers; 4 | 5 | unittest // stringSlicing 6 | { 7 | auto sentence = "The quick brown fox"; 8 | assert(sentence[0] == FILL_IN_THIS_CHAR); 9 | assert(sentence[1 .. 3] == FILL_IN_THIS_STRING); 10 | assert(sentence[$ - 1] == FILL_IN_THIS_CHAR); 11 | assert(sentence[$ - 3 .. $] == FILL_IN_THIS_STRING); 12 | } 13 | 14 | unittest // stringConcatenation() 15 | { 16 | auto str1 = "Hello"; 17 | auto str2 = " World"; 18 | auto str = str1 ~ str2; 19 | assert(str == FILL_IN_THIS_STRING); 20 | } 21 | 22 | unittest // stringsAreImmutable() 23 | { 24 | auto str = "hello"; 25 | // we cannot do this: 26 | // str[0]='H'; why? 27 | // but we must get a mutable reference before 28 | char[] s = str.dup; 29 | s[0] = 'H'; 30 | assert(s == FILL_IN_THIS_STRING); 31 | } 32 | 33 | unittest // stringLiterals() 34 | { 35 | auto str1 = `c:\nurten`; // \n is not getting interpreted as newline 36 | auto str2 = r"c:\nurten"; // same here 37 | assert(str1 == FILL_IN_THIS_STRING); 38 | assert(str2 == FILL_IN_THIS_STRING); 39 | } 40 | 41 | unittest // unicodeLiterals() 42 | { 43 | string s = "résumé"c; // same as "résumé" 44 | wstring w = "résumé"w; 45 | dstring d = "résumé"d; 46 | 47 | assert(s.length == FILL_IN_THIS_NUMBER); 48 | assert(w.length == FILL_IN_THIS_NUMBER); 49 | assert(d.length == FILL_IN_THIS_NUMBER); 50 | } 51 | -------------------------------------------------------------------------------- /koans/concurrency.d: -------------------------------------------------------------------------------- 1 | module koans.concurrency; 2 | 3 | import koans.helpers; 4 | 5 | import std.concurrency; 6 | import core.thread; 7 | import std.stdio : write; 8 | 9 | //this function will run in another thread 10 | //also showing simple message passing 11 | void worker2xFunc(Tid tid) 12 | { 13 | int value = 0; 14 | while (value >= 0) 15 | { 16 | value = receiveOnly!int(); 17 | auto result = value * 2; 18 | tid.send(result); 19 | } 20 | } 21 | 22 | //this function will run in another thread 23 | //also showing message passing with wait and timeout 24 | void workerSlowFunc(Tid tid) 25 | { 26 | //tid.send("starting..."); 27 | Thread.sleep(dur!("msecs")(500),); 28 | tid.send("done!"); 29 | } 30 | 31 | unittest // collect_doubles() 32 | { 33 | Tid worker = spawn(&worker2xFunc, thisTid); 34 | int sum = 0; 35 | foreach (value; 1 .. 3) 36 | { 37 | worker.send(value); 38 | auto result = receiveOnly!int(); 39 | sum += result; 40 | } 41 | worker.send(-1); //signal worker to end 42 | assert(sum == FILL_IN_THIS_NUMBER); 43 | } 44 | 45 | unittest // wait_for_result() 46 | { 47 | Tid _ = spawn(&workerSlowFunc, thisTid); 48 | bool received = false; 49 | while (!received) 50 | { 51 | received = receiveTimeout(dur!("msecs")(100), (string message) { 52 | assert(message == FILL_IN_THIS_STRING); 53 | }); 54 | if (!received) 55 | write("."); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /koans/lambda_syntax.d: -------------------------------------------------------------------------------- 1 | module koans.lambda_syntax; 2 | 3 | import koans.helpers; 4 | 5 | // the new "lambda" (anonymous function) syntax was introduced in DMD 2.058 6 | 7 | import std.algorithm : filter; 8 | import std.array : array; 9 | 10 | bool myfunc(int number) 11 | { 12 | return number < 20; 13 | } 14 | 15 | unittest // try_lambda_syntax() 16 | { 17 | const int[] numbers = [20, 1, 10, 300, -2]; 18 | 19 | // filter returns all the values where the given function is true 20 | 21 | //showing the "old" way , passing a pre-defined function 22 | auto filtered_with_defined_func = numbers.filter!(myfunc); 23 | 24 | // we can instead pass an anonymous function 25 | auto filtered_with_anon_func = numbers.filter!(function bool(x) { 26 | return x < 20; 27 | }); 28 | // 'function' keyword is not necessary, so 29 | // 'bool(x) { return x < 20; }' 30 | // also works; the return type can be inferred, so the above can be written as 31 | // auto filtered_with_anon_func=numbers.filter!( x { return x < 20; }); 32 | 33 | // and now let's replace the return and curly braces with the "new" lambda syntax 34 | auto filtered_with_lambda = numbers.filter!(n => n < 20); 35 | assert(filtered_with_defined_func.array == filtered_with_anon_func.array); // converted to array, 36 | assert(filtered_with_defined_func.array == filtered_with_lambda.array); // results are the same 37 | 38 | assert(filtered_with_lambda.array.length == FILL_IN_THIS_NUMBER); 39 | } 40 | -------------------------------------------------------------------------------- /koans/associative_arrays.d: -------------------------------------------------------------------------------- 1 | module koans.associative_arrays; 2 | 3 | import koans.helpers; 4 | 5 | unittest // creation_and_assignment() 6 | { 7 | int[string] mymap; 8 | mymap["hello"] = 3; 9 | assert(mymap["hello"] == FILL_IN_THIS_NUMBER); 10 | } 11 | 12 | unittest // other_operations() 13 | { 14 | int[string] ages = ["bob": 20, "joe": 30, "dan": 40]; 15 | 16 | assert(ages.length == FILL_IN_THIS_NUMBER); 17 | 18 | auto age = ages["bob"]; 19 | assert(age == FILL_IN_THIS_NUMBER); 20 | 21 | ages["bob"] = 77; 22 | assert(ages["bob"] == FILL_IN_THIS_NUMBER); 23 | 24 | import core.exception : RangeError; 25 | 26 | try 27 | { 28 | age = ages["steven"]; 29 | } 30 | catch (RangeError e) 31 | { 32 | // accessing non existing elements raise an exception 33 | assert(e.msg == FILL_IN_THIS_STRING); 34 | } 35 | 36 | ages["steven"] = 66; //new ones can be added 37 | assert(ages["steven"] == FILL_IN_THIS_NUMBER); 38 | 39 | assert(ages.length == FILL_IN_THIS_NUMBER); 40 | 41 | ages.remove("joe"); // you can also remove elements 42 | 43 | assert(ages.length == FILL_IN_THIS_NUMBER); 44 | } 45 | 46 | unittest // keys_and_values() 47 | { 48 | string[string] colors = [ 49 | "black": "000000", "white": "FFFFFF", "red": "FF0000", 50 | "green": "00FF00", "blue": "0000FF" 51 | ]; 52 | assert(colors.keys.length == FILL_IN_THIS_NUMBER); // .keys gives an array with all the keys 53 | assert(colors.values.length == FILL_IN_THIS_NUMBER); // same for .values 54 | 55 | } 56 | -------------------------------------------------------------------------------- /koans/function_parameters.d: -------------------------------------------------------------------------------- 1 | module koans.function_parameters; 2 | 3 | import koans.helpers; 4 | 5 | // parameters are passed by value as default and ALWAYS copied 6 | 7 | void decrement(int value) 8 | { 9 | value -= 10; 10 | } 11 | 12 | unittest // testParameterByValue() 13 | { 14 | auto number = 100; 15 | decrement(number); 16 | assert(number == FILL_IN_THIS_NUMBER); 17 | } 18 | 19 | // ... this is also true for slices 20 | // but you can force the reference semantic by adding a "ref" qualifier 21 | 22 | void wrong_append(int[] arr, int elem) 23 | { 24 | arr ~= elem; // this doesn't work as expected 25 | } 26 | 27 | void right_append(ref int[] arr, int elem) 28 | { 29 | arr ~= elem; // that's better 30 | } 31 | 32 | unittest // testSliceParameter() 33 | { 34 | 35 | auto my_array = [4, 8, 15, 16, 23]; 36 | wrong_append(my_array, 42); 37 | assert(my_array.length == FILL_IN_THIS_NUMBER); 38 | right_append(my_array, 42); 39 | assert(my_array.length == FILL_IN_THIS_NUMBER); 40 | } 41 | 42 | // parameters can have "in" and "out" qualifiers, 43 | // where "in" stands for input and 44 | // "out" for values that will be returned to the caller 45 | 46 | int sumAndProduct(in int n1, in int n2, out int product) 47 | { 48 | product = n1 * n2; 49 | return n1 + n2; 50 | } 51 | 52 | unittest // exerciseInOutParameters() 53 | { 54 | int prod; 55 | int result = sumAndProduct(7, 3, prod); 56 | assert(result == FILL_IN_THIS_NUMBER); 57 | assert(prod == FILL_IN_THIS_NUMBER); 58 | } 59 | 60 | /*-----------------------------------------*/ 61 | -------------------------------------------------------------------------------- /koans/classes.d: -------------------------------------------------------------------------------- 1 | module koans.classes; 2 | 3 | import koans.helpers; 4 | 5 | class A 6 | { 7 | private int myValue; // not accessible from outside 8 | 9 | this(int startValue) 10 | { // constructor 11 | myValue = startValue; 12 | } 13 | 14 | } 15 | 16 | class B : A 17 | { 18 | this() 19 | { 20 | super(3); // what happens here ? 21 | } 22 | 23 | auto getDoubleValue() 24 | { 25 | return myValue * 2; // B doesn't have this field but.. 26 | } 27 | } 28 | 29 | unittest // inheritance() 30 | { 31 | auto instance = new B; 32 | assert(instance.getDoubleValue() == FILL_IN_THIS_NUMBER); 33 | } 34 | 35 | // code preparation for next test 36 | struct TimeOfDay_s 37 | { 38 | int hour; 39 | int minute; 40 | } 41 | 42 | class TimeOfDay_c 43 | { 44 | int hour; 45 | int minute; 46 | } 47 | 48 | void set_time(TimeOfDay_c tc, int hour, int min) 49 | { 50 | tc.hour = hour; 51 | tc.minute = min; 52 | } 53 | 54 | void set_time(TimeOfDay_s ts, int hour, int min) 55 | { 56 | ts.hour = hour; 57 | ts.minute = min; 58 | } 59 | 60 | unittest // class_vs_struct() 61 | { 62 | TimeOfDay_s timestruct; // memory allocated on the stack 63 | TimeOfDay_c timeclass; 64 | // here timeclass it's a null pointer! 65 | // must allocate space and initialize fields... 66 | timeclass = new TimeOfDay_c; // object is created on the heap 67 | set_time(timestruct, 15, 10); 68 | set_time(timeclass, 15, 10); 69 | 70 | assert(timestruct.hour == FILL_IN_THIS_NUMBER); //surprised ? 71 | assert(timeclass.hour == FILL_IN_THIS_NUMBER); //classes are reference type 72 | } 73 | -------------------------------------------------------------------------------- /koans/arrays.d: -------------------------------------------------------------------------------- 1 | module koans.arrays; 2 | 3 | import koans.helpers; 4 | 5 | unittest // fixed_length_arrays() 6 | { 7 | string[4] fruits = ["banana", "mango", "apple", "orange"]; 8 | assert(fruits[0] == FILL_IN_THIS_STRING); 9 | assert(fruits.length == FILL_IN_THIS_NUMBER); 10 | int[5] b = 1; // 5 elements with same value 1 11 | assert(b == FILL_IN_THIS_ARRAY); 12 | } 13 | 14 | unittest // dynamic_length_arrays() 15 | { 16 | string[] fruits = ["banana", "mango"]; 17 | assert(fruits.length == FILL_IN_THIS_NUMBER); 18 | fruits ~= "strawberry"; 19 | assert(fruits.length == FILL_IN_THIS_NUMBER); 20 | assert(fruits[2] == FILL_IN_THIS_STRING); 21 | } 22 | 23 | unittest // array_slicing() 24 | { 25 | int[] a = [4, 3, 2, 1]; 26 | a[0 .. 2] = [1, 2]; 27 | assert(a == FILL_IN_THIS_ARRAY); 28 | a[0 .. $] = [0, 0, 0, 0]; // $ is always the last element 29 | assert(a == FILL_IN_THIS_ARRAY); 30 | } 31 | 32 | unittest // array_append() 33 | { 34 | int[] a; 35 | a.length = 3; // length extended, elements using default value 36 | assert(a == FILL_IN_THIS_ARRAY); 37 | a ~= [3, 4]; 38 | assert(a == FILL_IN_THIS_ARRAY); 39 | } 40 | 41 | unittest // slices_of_the_same_array() 42 | { 43 | int[] items = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]; 44 | auto slice1 = items[2 .. 9]; 45 | auto slice2 = items[4 .. 7]; 46 | assert(slice1[0] == FILL_IN_THIS_NUMBER); 47 | assert(slice2[0] == FILL_IN_THIS_NUMBER); 48 | slice1[3] = 99; 49 | assert(slice2[1] == FILL_IN_THIS_NUMBER); 50 | slice2.length = 2; //truncating a slice... 51 | assert(items.length == FILL_IN_THIS_NUMBER); // ... changes original array lenght ? 52 | } 53 | -------------------------------------------------------------------------------- /koans/delegates.d: -------------------------------------------------------------------------------- 1 | module koans.delegates; 2 | 3 | import koans.helpers; 4 | 5 | // Delegates are function pointers with context information attached. 6 | int delegate(int) call_me_later; // a delegate which takes an int and returns an int 7 | 8 | class Foo 9 | { 10 | private int y; 11 | 12 | //constructor 13 | this(int value) 14 | { 15 | y = value; 16 | } 17 | 18 | int mymethod(int x) 19 | { 20 | return x + y; 21 | } 22 | } 23 | 24 | unittest // explicit_delegate() 25 | { 26 | Foo foo = new Foo(3); 27 | call_me_later = &foo.mymethod; 28 | auto result = call_me_later(5); // call mymethod(5) 29 | assert(result == FILL_IN_THIS_NUMBER); 30 | } 31 | 32 | // -------------------------------------------------------------------------------- 33 | // delegates are useful as "event receivers". Let's define a simple GUI-like class 34 | 35 | alias ClickHandler = void delegate(Button); 36 | 37 | class Button 38 | { 39 | 40 | private ClickHandler[] handlers; 41 | 42 | private int click_counter; //some button properties 43 | private string name = "UNTITLED"; 44 | private string color = "DEFAULT"; 45 | 46 | void click() 47 | { // executes user defined callbacks 48 | // giving each callback full access to this "Button" context 49 | foreach (h; handlers) 50 | { 51 | h(this); 52 | } 53 | click_counter++; 54 | } 55 | 56 | void registerHandler(ClickHandler func) 57 | { 58 | handlers ~= func; 59 | } 60 | 61 | @property string state() 62 | { 63 | import std.format : format; 64 | 65 | return format("you clicked %d times the button %s with color %s", 66 | click_counter, name, color); 67 | } 68 | 69 | } 70 | 71 | // now the class user can "attach" event handlers to instances of the class 72 | // in order to change class default behavior 73 | 74 | unittest // delegates_for_callback() 75 | { 76 | auto b1 = new Button(); 77 | auto b2 = new Button(); 78 | b1.registerHandler(delegate(Button b) { b.name = "OK"; }); 79 | b2.registerHandler(delegate(Button b) { b.color = "RED"; }); 80 | b2.registerHandler(delegate(Button b) { b.click_counter--; }); // can be chained 81 | b1.click(); 82 | b1.click(); 83 | b2.click(); 84 | b2.click(); 85 | assert(b1.state == FILL_IN_THIS_STRING); 86 | assert(b2.state == FILL_IN_THIS_STRING); 87 | } 88 | -------------------------------------------------------------------------------- /dscanner.ini: -------------------------------------------------------------------------------- 1 | ; Configure which static analysis checks are enabled 2 | [analysis.config.StaticAnalysisConfig] 3 | ; Check variable, class, struct, interface, union, and function names against t 4 | ; he Phobos style guide 5 | style_check="enabled" 6 | ; Check for array literals that cause unnecessary allocation 7 | enum_array_literal_check="enabled" 8 | ; Check for poor exception handling practices 9 | exception_check="enabled" 10 | ; Check for use of the deprecated 'delete' keyword 11 | delete_check="enabled" 12 | ; Check for use of the deprecated floating point operators 13 | float_operator_check="enabled" 14 | ; Check number literals for readability 15 | number_style_check="enabled" 16 | ; Checks that opEquals, opCmp, toHash, and toString are either const, immutable 17 | ; , or inout. 18 | object_const_check="enabled" 19 | ; Checks for .. expressions where the left side is larger than the right. 20 | backwards_range_check="enabled" 21 | ; Checks for if statements whose 'then' block is the same as the 'else' block 22 | if_else_same_check="enabled" 23 | ; Checks for some problems with constructors 24 | constructor_check="enabled" 25 | ; Checks for unused variables and function parameters 26 | unused_variable_check="enabled" 27 | ; Checks for unused labels 28 | unused_label_check="enabled" 29 | ; Checks for duplicate attributes 30 | duplicate_attribute="enabled" 31 | ; Checks that opEquals and toHash are both defined or neither are defined 32 | opequals_tohash_check="enabled" 33 | ; Checks for subtraction from .length properties 34 | length_subtraction_check="enabled" 35 | ; Checks for methods or properties whose names conflict with built-in propertie 36 | ; s 37 | builtin_property_names_check="enabled" 38 | ; Checks for confusing code in inline asm statements 39 | asm_style_check="enabled" 40 | ; Checks for confusing logical operator precedence 41 | logical_precedence_check="enabled" 42 | ; Checks for undocumented public declarations 43 | undocumented_declaration_check="disabled" 44 | ; Checks for poor placement of function attributes 45 | function_attribute_check="enabled" 46 | ; Checks for use of the comma operator 47 | comma_expression_check="enabled" 48 | ; Checks for local imports that are too broad 49 | local_import_check="enabled" 50 | ; Checks for variables that could be declared immutable 51 | could_be_immutable_check="disabled" 52 | ; Checks for redundant expressions in if statements 53 | redundant_if_check="enabled" 54 | ; Checks for redundant parenthesis 55 | redundant_parens_check="enabled" 56 | ; Checks for mismatched argument and parameter names 57 | mismatched_args_check="enabled" 58 | ; Checks for labels with the same name as variables 59 | label_var_same_name_check="enabled" 60 | ; Checks for lines longer than 120 characters 61 | long_line_check="enabled" 62 | ; Checks for assignment to auto-ref function parameters 63 | auto_ref_assignment_check="enabled" 64 | ; Checks for incorrect infinite range definitions 65 | incorrect_infinite_range_check="enabled" 66 | ; Checks for asserts that are always true 67 | useless_assert_check="enabled" 68 | ; Check for uses of the old-style alias syntax 69 | alias_syntax_check="enabled" 70 | ; Checks for else if that should be else static if 71 | static_if_else_check="enabled" 72 | ; Check for unclear lambda syntax 73 | lambda_return_check="enabled" 74 | ; Check for auto function without return statement 75 | auto_function_check="enabled" 76 | ; Check for sortedness of imports 77 | imports_sortedness="disabled" 78 | ; Check for explicitly annotated unittests 79 | explicitly_annotated_unittests="disabled" 80 | ; Check for properly documented public functions (Returns, Params) 81 | properly_documented_public_functions="disabled" 82 | ; Check for useless usage of the final attribute 83 | final_attribute_check="enabled" 84 | ; Check for virtual calls in the class constructors 85 | vcall_in_ctor="enabled" 86 | ; Check for useless user defined initializers 87 | useless_initializer="disabled" 88 | ; Check allman brace style 89 | allman_braces_check="disabled" 90 | ; Check for redundant attributes 91 | redundant_attributes_check="enabled" 92 | ; Check public declarations without a documented unittest 93 | has_public_example="disabled" 94 | ; Check for asserts without an explanatory message 95 | assert_without_msg="disabled" 96 | ; Check indent of if constraints 97 | if_constraints_indent="disabled" 98 | ; Check for @trusted applied to a bigger scope than a single function 99 | trust_too_much="enabled" 100 | ; Check for redundant storage classes on variable declarations 101 | redundant_storage_classes="enabled" 102 | ; ModuleFilters for selectively enabling (+std) and disabling (-std.internal) i 103 | ; ndividual checks 104 | [analysis.config.ModuleFilters] 105 | ; Exclude/Import modules 106 | style_check="" 107 | ; Exclude/Import modules 108 | enum_array_literal_check="" 109 | ; Exclude/Import modules 110 | exception_check="" 111 | ; Exclude/Import modules 112 | delete_check="" 113 | ; Exclude/Import modules 114 | float_operator_check="" 115 | ; Exclude/Import modules 116 | number_style_check="" 117 | ; Exclude/Import modules 118 | object_const_check="" 119 | ; Exclude/Import modules 120 | backwards_range_check="" 121 | ; Exclude/Import modules 122 | if_else_same_check="" 123 | ; Exclude/Import modules 124 | constructor_check="" 125 | ; Exclude/Import modules 126 | unused_variable_check="" 127 | ; Exclude/Import modules 128 | unused_label_check="" 129 | ; Exclude/Import modules 130 | duplicate_attribute="" 131 | ; Exclude/Import modules 132 | opequals_tohash_check="" 133 | ; Exclude/Import modules 134 | length_subtraction_check="" 135 | ; Exclude/Import modules 136 | builtin_property_names_check="" 137 | ; Exclude/Import modules 138 | asm_style_check="" 139 | ; Exclude/Import modules 140 | logical_precedence_check="" 141 | ; Exclude/Import modules 142 | undocumented_declaration_check="" 143 | ; Exclude/Import modules 144 | function_attribute_check="" 145 | ; Exclude/Import modules 146 | comma_expression_check="" 147 | ; Exclude/Import modules 148 | local_import_check="" 149 | ; Exclude/Import modules 150 | could_be_immutable_check="" 151 | ; Exclude/Import modules 152 | redundant_if_check="" 153 | ; Exclude/Import modules 154 | redundant_parens_check="" 155 | ; Exclude/Import modules 156 | mismatched_args_check="" 157 | ; Exclude/Import modules 158 | label_var_same_name_check="" 159 | ; Exclude/Import modules 160 | long_line_check="" 161 | ; Exclude/Import modules 162 | auto_ref_assignment_check="" 163 | ; Exclude/Import modules 164 | incorrect_infinite_range_check="" 165 | ; Exclude/Import modules 166 | useless_assert_check="" 167 | ; Exclude/Import modules 168 | alias_syntax_check="" 169 | ; Exclude/Import modules 170 | static_if_else_check="" 171 | ; Exclude/Import modules 172 | lambda_return_check="" 173 | ; Exclude/Import modules 174 | auto_function_check="" 175 | ; Exclude/Import modules 176 | imports_sortedness="" 177 | ; Exclude/Import modules 178 | explicitly_annotated_unittests="" 179 | ; Exclude/Import modules 180 | properly_documented_public_functions="" 181 | ; Exclude/Import modules 182 | final_attribute_check="" 183 | ; Exclude/Import modules 184 | vcall_in_ctor="" 185 | ; Exclude/Import modules 186 | useless_initializer="" 187 | ; Exclude/Import modules 188 | allman_braces_check="" 189 | ; Exclude/Import modules 190 | redundant_attributes_check="" 191 | ; Exclude/Import modules 192 | has_public_example="" 193 | ; Exclude/Import modules 194 | assert_without_msg="" 195 | ; Exclude/Import modules 196 | if_constraints_indent="" 197 | ; Exclude/Import modules 198 | trust_too_much="" 199 | ; Exclude/Import modules 200 | redundant_storage_classes="" 201 | --------------------------------------------------------------------------------