trackler 2.2.1.77 → 2.2.1.78
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/problem-specifications/exercises/transpose/canonical-data.json +94 -116
- data/tracks/bash/config/maintainers.json +11 -1
- data/tracks/clojure/config.json +10 -2
- data/tracks/clojure/exercises/reverse-string/README.md +14 -0
- data/tracks/clojure/exercises/reverse-string/project.clj +4 -0
- data/tracks/clojure/exercises/reverse-string/src/example.clj +5 -0
- data/tracks/clojure/exercises/reverse-string/src/reverse_string.clj +5 -0
- data/tracks/clojure/exercises/reverse-string/test/reverse_string_test.clj +18 -0
- data/tracks/clojure/exercises/say/README.md +70 -0
- data/tracks/clojure/exercises/{two-fer → say}/project.clj +3 -3
- data/tracks/clojure/exercises/say/src/example.clj +9 -0
- data/tracks/clojure/exercises/say/src/say.clj +5 -0
- data/tracks/clojure/exercises/say/test/say_test.clj +48 -0
- data/tracks/coffeescript/docs/ABOUT.md +4 -9
- data/tracks/coffeescript/docs/INSTALLATION.md +2 -2
- data/tracks/erlang/exercises/pangram/rebar.config +1 -1
- data/tracks/erlang/exercises/pangram/src/example.erl +2 -3
- data/tracks/erlang/exercises/pangram/test/pangram_tests.erl +12 -13
- data/tracks/fsharp/exercises/grep/Example.fs +16 -20
- data/tracks/fsharp/exercises/grep/GrepTest.fs +154 -233
- data/tracks/fsharp/generators/Common.fs +7 -2
- data/tracks/fsharp/generators/Exercise.fs +51 -16
- data/tracks/fsharp/generators/Formatting.fs +13 -6
- data/tracks/fsharp/generators/Generators.fs +44 -14
- data/tracks/fsharp/generators/Rendering.fs +8 -1
- data/tracks/fsharp/generators/Templates/Generators/_GrepSetup.liquid +37 -0
- data/tracks/fsharp/generators/Templates/_TestClass.liquid +9 -3
- data/tracks/fsharp/generators/Templates/{_TestMethod.liquid → _TestFunction.liquid} +0 -0
- data/tracks/fsharp/generators/Templates/{_TestMethodBody.liquid → _TestFunctionBody.liquid} +0 -0
- data/tracks/fsharp/generators/Templates/_TestMember.liquid +3 -0
- data/tracks/fsharp/generators/Templates/_TestMemberBody.liquid +4 -0
- data/tracks/fsharp/generators/Templates/_TestModule.liquid +17 -0
- data/tracks/go/config.json +24 -0
- data/tracks/go/exercises/acronym/.meta/gen.go +5 -3
- data/tracks/go/exercises/acronym/acronym.go +0 -2
- data/tracks/go/exercises/acronym/cases_test.go +2 -2
- data/tracks/go/exercises/acronym/example.go +2 -3
- data/tracks/go/exercises/all-your-base/.meta/gen.go +9 -7
- data/tracks/go/exercises/all-your-base/cases_test.go +2 -2
- data/tracks/go/exercises/allergies/.meta/gen.go +10 -6
- data/tracks/go/exercises/allergies/cases_test.go +2 -2
- data/tracks/go/exercises/anagram/.meta/gen.go +7 -5
- data/tracks/go/exercises/anagram/cases_test.go +2 -2
- data/tracks/go/exercises/armstrong-numbers/.meta/gen.go +54 -0
- data/tracks/go/exercises/armstrong-numbers/armstrong_test.go +12 -0
- data/tracks/go/exercises/armstrong-numbers/cases_test.go +52 -0
- data/tracks/go/exercises/armstrong-numbers/example.go +24 -0
- data/tracks/go/exercises/binary-search/.meta/gen.go +7 -5
- data/tracks/go/exercises/binary-search/cases_test.go +2 -2
- data/tracks/go/exercises/book-store/.meta/gen.go +5 -3
- data/tracks/go/exercises/book-store/cases_test.go +2 -2
- data/tracks/go/exercises/connect/example.go +4 -5
- data/tracks/go/exercises/dominoes/.meta/gen.go +61 -0
- data/tracks/go/exercises/dominoes/.meta/hints.md +29 -0
- data/tracks/go/exercises/dominoes/README.md +67 -0
- data/tracks/go/exercises/dominoes/cases_test.go +72 -0
- data/tracks/go/exercises/dominoes/dominoes_test.go +106 -0
- data/tracks/go/exercises/dominoes/example.go +146 -0
- data/tracks/go/exercises/ledger/example.go +1 -1
- data/tracks/groovy/.gitignore +3 -0
- data/tracks/groovy/.travis.yml +10 -1
- data/tracks/groovy/bin/prepeare_exercise_builds.groovy +77 -0
- data/tracks/groovy/build.gradle +25 -0
- data/tracks/groovy/exercises/difference-of-squares/Example.groovy +3 -3
- data/tracks/groovy/exercises/gigasecond/GigasecondSpec.groovy +3 -3
- data/tracks/groovy/exercises/linked-list/{DoubleLinkedList.groovy → LinkedList.groovy} +0 -0
- data/tracks/groovy/exercises/linked-list/{DoubleLinkedListSpec.groovy → LinkedListSpec.groovy} +0 -0
- data/tracks/groovy/exercises/linked-list/README.md +1 -1
- data/tracks/groovy/gradle/wrapper/gradle-wrapper.jar +0 -0
- data/tracks/groovy/gradle/wrapper/gradle-wrapper.properties +6 -0
- data/tracks/groovy/gradlew +172 -0
- data/tracks/groovy/gradlew.bat +84 -0
- data/tracks/groovy/settings.gradle +9 -0
- data/tracks/ocaml/exercises/acronym/.merlin +1 -1
- data/tracks/ocaml/exercises/all-your-base/.merlin +1 -1
- data/tracks/ocaml/exercises/anagram/.merlin +1 -1
- data/tracks/ocaml/exercises/atbash-cipher/.merlin +1 -1
- data/tracks/ocaml/exercises/beer-song/.merlin +1 -1
- data/tracks/ocaml/exercises/binary-search/.merlin +1 -1
- data/tracks/ocaml/exercises/bob/.merlin +1 -1
- data/tracks/ocaml/exercises/bowling/.merlin +1 -1
- data/tracks/ocaml/exercises/change/.merlin +1 -1
- data/tracks/ocaml/exercises/difference-of-squares/.merlin +1 -1
- data/tracks/ocaml/exercises/etl/.merlin +1 -1
- data/tracks/ocaml/exercises/forth/.merlin +1 -1
- data/tracks/ocaml/exercises/grade-school/.merlin +1 -1
- data/tracks/ocaml/exercises/hamming/.merlin +1 -1
- data/tracks/ocaml/exercises/hangman/.merlin +1 -1
- data/tracks/ocaml/exercises/hello-world/.merlin +1 -1
- data/tracks/ocaml/exercises/hexadecimal/.merlin +1 -1
- data/tracks/ocaml/exercises/leap/.merlin +1 -1
- data/tracks/ocaml/exercises/list-ops/.merlin +1 -1
- data/tracks/ocaml/exercises/luhn/.merlin +1 -1
- data/tracks/ocaml/exercises/meetup/.merlin +1 -1
- data/tracks/ocaml/exercises/minesweeper/.merlin +1 -1
- data/tracks/ocaml/exercises/nucleotide-count/.merlin +1 -1
- data/tracks/ocaml/exercises/phone-number/.merlin +1 -1
- data/tracks/ocaml/exercises/prime-factors/.merlin +1 -1
- data/tracks/ocaml/exercises/raindrops/.merlin +1 -1
- data/tracks/ocaml/exercises/react/.merlin +1 -1
- data/tracks/ocaml/exercises/rectangles/.merlin +1 -1
- data/tracks/ocaml/exercises/rna-transcription/.merlin +1 -1
- data/tracks/ocaml/exercises/run-length-encoding/.merlin +1 -1
- data/tracks/ocaml/exercises/say/.merlin +1 -1
- data/tracks/ocaml/exercises/space-age/.merlin +1 -1
- data/tracks/ocaml/exercises/triangle/.merlin +1 -1
- data/tracks/ocaml/exercises/word-count/.merlin +1 -1
- data/tracks/ocaml/exercises/zipper/.merlin +1 -1
- data/tracks/typescript/config/maintainers.json +2 -2
- metadata +37 -12
- data/tracks/clojure/exercises/two-fer/README.md +0 -19
- data/tracks/clojure/exercises/two-fer/src/example.clj +0 -5
- data/tracks/clojure/exercises/two-fer/src/two_fer.clj +0 -5
- data/tracks/clojure/exercises/two-fer/test/two_fer_test.clj +0 -12
- data/tracks/erlang/exercises/pangram/include/exercism.hrl +0 -11
@@ -31,13 +31,18 @@ type TestMethodBodyAssert =
|
|
31
31
|
{ Sut: string
|
32
32
|
Expected: string }
|
33
33
|
|
34
|
-
type
|
34
|
+
type TestFile =
|
35
35
|
{ Version: string
|
36
36
|
ExerciseName: string
|
37
37
|
TestModuleName: string
|
38
38
|
TestedModuleName: string
|
39
39
|
Namespaces: string list
|
40
|
-
Methods: string list
|
40
|
+
Methods: string list
|
41
|
+
Setup: string }
|
42
|
+
|
43
|
+
type TestFileFormat =
|
44
|
+
| Module
|
45
|
+
| Class
|
41
46
|
|
42
47
|
module Logging =
|
43
48
|
let setupLogger() =
|
@@ -23,17 +23,24 @@ type GeneratorExercise() =
|
|
23
23
|
abstract member MapCanonicalDataCaseProperty : CanonicalDataCase * string * obj -> obj
|
24
24
|
|
25
25
|
// Convert canonical data to representation used when rendering
|
26
|
-
abstract member
|
26
|
+
abstract member ToTestFile : CanonicalData -> TestFile
|
27
27
|
abstract member ToTestMethod : int * CanonicalDataCase -> TestMethod
|
28
28
|
abstract member ToTestMethodBody : CanonicalDataCase -> TestMethodBody
|
29
29
|
abstract member ToTestMethodBodyAssert : CanonicalDataCase -> TestMethodBodyAssert
|
30
|
-
|
30
|
+
|
31
|
+
// Determine the templates to use when rendering
|
32
|
+
abstract member TestFileTemplate : string
|
33
|
+
abstract member TestMethodTemplate : int * CanonicalDataCase -> string
|
34
|
+
abstract member TestMethodBodyTemplate : CanonicalDataCase -> string
|
35
|
+
abstract member TestMethodBodyAssertTemplate : CanonicalDataCase -> string
|
36
|
+
abstract member TestFileFormat: TestFileFormat
|
31
37
|
|
32
38
|
// Rendering of canonical data
|
33
39
|
abstract member Render : CanonicalData -> string
|
34
|
-
abstract member RenderTestMethod : int
|
40
|
+
abstract member RenderTestMethod : int * CanonicalDataCase -> string
|
35
41
|
abstract member RenderTestMethodBody : CanonicalDataCase -> string
|
36
42
|
abstract member RenderTestMethodName : CanonicalDataCase -> string
|
43
|
+
abstract member RenderSetup : CanonicalData -> string
|
37
44
|
|
38
45
|
// Generic value/identifier rendering methods
|
39
46
|
abstract member RenderValue : CanonicalDataCase * string * obj -> string
|
@@ -66,10 +73,10 @@ type GeneratorExercise() =
|
|
66
73
|
member this.TestedModuleName = this.GetType().Name.Pascalize()
|
67
74
|
|
68
75
|
member this.WriteToFile contents =
|
69
|
-
let
|
76
|
+
let testFilePath = Path.Combine("..", "exercises", this.Name, sprintf "%s.fs" this.TestModuleName)
|
70
77
|
|
71
|
-
Directory.CreateDirectory(Path.GetDirectoryName(
|
72
|
-
File.WriteAllText(
|
78
|
+
Directory.CreateDirectory(Path.GetDirectoryName(testFilePath)) |> ignore
|
79
|
+
File.WriteAllText(testFilePath, contents)
|
73
80
|
|
74
81
|
member this.Regenerate(canonicalData) =
|
75
82
|
canonicalData
|
@@ -94,13 +101,16 @@ type GeneratorExercise() =
|
|
94
101
|
|
95
102
|
// Convert canonical data to representation used when rendering
|
96
103
|
|
97
|
-
default this.
|
104
|
+
default this.ToTestFile canonicalData =
|
105
|
+
let renderTestMethod i canonicalDataCase = this.RenderTestMethod(i, canonicalDataCase)
|
106
|
+
|
98
107
|
{ Version = canonicalData.Version
|
99
108
|
ExerciseName = this.Name
|
100
109
|
TestModuleName = this.TestModuleName
|
101
110
|
TestedModuleName = this.TestedModuleName
|
102
111
|
Namespaces = ["FsUnit.Xunit"; "Xunit"] @ this.AdditionalNamespaces
|
103
|
-
Methods = List.mapi
|
112
|
+
Methods = List.mapi renderTestMethod canonicalData.Cases
|
113
|
+
Setup = this.RenderSetup canonicalData }
|
104
114
|
|
105
115
|
default this.ToTestMethod (index, canonicalDataCase) =
|
106
116
|
{ Skip = index > 0
|
@@ -115,27 +125,50 @@ type GeneratorExercise() =
|
|
115
125
|
{ Sut = this.RenderSut canonicalDataCase
|
116
126
|
Expected = this.RenderValueOrIdentifier (canonicalDataCase, "expected", canonicalDataCase.Expected) }
|
117
127
|
|
118
|
-
|
128
|
+
// Determine the templates to use when rendering
|
129
|
+
|
130
|
+
default this.TestFileTemplate =
|
131
|
+
match this.TestFileFormat with
|
132
|
+
| Module -> "TestModule"
|
133
|
+
| Class -> "TestClass"
|
134
|
+
|
135
|
+
default this.TestMethodTemplate (_, _) =
|
136
|
+
match this.TestFileFormat with
|
137
|
+
| Module -> "TestFunction"
|
138
|
+
| Class -> "TestMember"
|
139
|
+
|
140
|
+
default this.TestMethodBodyTemplate _ =
|
141
|
+
match this.TestFileFormat with
|
142
|
+
| Module -> "TestFunctionBody"
|
143
|
+
| Class -> "TestMemberBody"
|
144
|
+
|
145
|
+
default this.TestMethodBodyAssertTemplate canonicalDataCase =
|
119
146
|
match canonicalDataCase.Expected with
|
120
147
|
| :? JArray as jArray when jArray.Count = 0 && not (List.contains "expected" (this.PropertiesWithIdentifier canonicalDataCase)) -> "AssertEmpty"
|
121
148
|
| _ -> "AssertEqual"
|
122
149
|
|
150
|
+
default __.TestFileFormat = TestFileFormat.Module
|
151
|
+
|
123
152
|
// Rendering of canonical data
|
124
153
|
|
125
154
|
default this.Render canonicalData =
|
126
155
|
canonicalData
|
127
|
-
|> this.
|
128
|
-
|> renderPartialTemplate
|
156
|
+
|> this.ToTestFile
|
157
|
+
|> renderPartialTemplate this.TestFileTemplate
|
158
|
+
|
159
|
+
default this.RenderTestMethod (index, canonicalDataCase) =
|
160
|
+
let template = this.TestMethodTemplate (index, canonicalDataCase)
|
129
161
|
|
130
|
-
default this.RenderTestMethod index canonicalDataCase =
|
131
162
|
(index, canonicalDataCase)
|
132
163
|
|> this.ToTestMethod
|
133
|
-
|> renderPartialTemplate
|
164
|
+
|> renderPartialTemplate template
|
134
165
|
|
135
166
|
default this.RenderTestMethodBody canonicalDataCase =
|
167
|
+
let template = this.TestMethodBodyTemplate canonicalDataCase
|
168
|
+
|
136
169
|
canonicalDataCase
|
137
170
|
|> this.ToTestMethodBody
|
138
|
-
|> renderPartialTemplate
|
171
|
+
|> renderPartialTemplate template
|
139
172
|
|
140
173
|
default this.RenderTestMethodName canonicalDataCase =
|
141
174
|
match this.UseFullMethodName canonicalDataCase with
|
@@ -144,7 +177,9 @@ type GeneratorExercise() =
|
|
144
177
|
| true ->
|
145
178
|
canonicalDataCase.DescriptionPath
|
146
179
|
|> String.concat " - "
|
147
|
-
|> String.upperCaseFirst
|
180
|
+
|> String.upperCaseFirst
|
181
|
+
|
182
|
+
default __.RenderSetup _ = ""
|
148
183
|
|
149
184
|
// Generic value/identifier rendering methods
|
150
185
|
|
@@ -195,7 +230,7 @@ type GeneratorExercise() =
|
|
195
230
|
|> List.choose renderArrangeProperty
|
196
231
|
|
197
232
|
default this.RenderAssert canonicalDataCase =
|
198
|
-
let template = this.
|
233
|
+
let template = this.TestMethodBodyAssertTemplate canonicalDataCase
|
199
234
|
|
200
235
|
canonicalDataCase
|
201
236
|
|> this.ToTestMethodBodyAssert
|
@@ -121,7 +121,7 @@ let rec formatValue (value: obj) =
|
|
121
121
|
| _ ->
|
122
122
|
string value
|
123
123
|
|
124
|
-
let formatCollection formatString collection =
|
124
|
+
let private formatCollection formatString collection =
|
125
125
|
collection
|
126
126
|
|> String.concat "; "
|
127
127
|
|> sprintf formatString
|
@@ -132,7 +132,7 @@ let formatArray sequence = formatCollection "[|%s|]" sequence
|
|
132
132
|
|
133
133
|
let formatSequence sequence = formatCollection "seq {%s}" sequence
|
134
134
|
|
135
|
-
let formatMultiLineCollection (openPrefix, closePostfix) collection =
|
135
|
+
let private formatMultiLineCollection (openPrefix, closePostfix) collection indentation =
|
136
136
|
match Seq.length collection with
|
137
137
|
| 0 ->
|
138
138
|
sprintf "%s%s" openPrefix closePostfix
|
@@ -153,15 +153,22 @@ let formatMultiLineCollection (openPrefix, closePostfix) collection =
|
|
153
153
|
collection
|
154
154
|
|> Seq.mapi formatLine
|
155
155
|
|> Seq.toList
|
156
|
-
|> List.map (indent
|
156
|
+
|> List.map (indent indentation)
|
157
157
|
|> String.concat "\n"
|
158
158
|
|> sprintf "\n%s"
|
159
159
|
|
160
|
-
let formatMultiLineList sequence = formatMultiLineCollection ("[", "]") sequence
|
161
160
|
|
162
|
-
let
|
161
|
+
let formatMultiLineListWithIndentation indentation sequence = formatMultiLineCollection ("[", "]") sequence indentation
|
163
162
|
|
164
|
-
let
|
163
|
+
let formatMultiLineArrayWithIndentation indentation sequence = formatMultiLineCollection ("[|", "|]") sequence indentation
|
164
|
+
|
165
|
+
let formatMultiLineSequenceWithIndentation indentation sequence = formatMultiLineCollection ("seq {", "}") sequence indentation
|
166
|
+
|
167
|
+
let formatMultiLineList sequence = formatMultiLineListWithIndentation 2 sequence
|
168
|
+
|
169
|
+
let formatMultiLineArray sequence = formatMultiLineArrayWithIndentation 2 sequence
|
170
|
+
|
171
|
+
let formatMultiLineSequence sequence = formatMultiLineSequenceWithIndentation 2 sequence
|
165
172
|
|
166
173
|
let formatMultiLineString strings =
|
167
174
|
let length = Seq.length strings
|
@@ -4,6 +4,7 @@ open System
|
|
4
4
|
open System.Globalization
|
5
5
|
open Newtonsoft.Json.Linq
|
6
6
|
open Formatting
|
7
|
+
open Rendering
|
7
8
|
open Exercise
|
8
9
|
|
9
10
|
type Acronym() =
|
@@ -61,7 +62,7 @@ type Allergies() =
|
|
61
62
|
type Alphametics() =
|
62
63
|
inherit GeneratorExercise()
|
63
64
|
|
64
|
-
member __.
|
65
|
+
member __.FormatMap<'TKey, 'TValue> (value: obj) =
|
65
66
|
if isNull value then
|
66
67
|
"None"
|
67
68
|
else
|
@@ -77,7 +78,7 @@ type Alphametics() =
|
|
77
78
|
else
|
78
79
|
sprintf "%s |> Map.ofList |> Some" formattedList
|
79
80
|
|
80
|
-
override this.RenderExpected (_, _, value) = this.
|
81
|
+
override this.RenderExpected (_, _, value) = this.FormatMap<char, int> value
|
81
82
|
|
82
83
|
override this.PropertiesWithIdentifier canonicalDataCase = this.Properties canonicalDataCase
|
83
84
|
|
@@ -164,7 +165,7 @@ type Clock() =
|
|
164
165
|
let minute = clock.["minute"].ToObject<string>()
|
165
166
|
sprintf "let %s = create %s %s" clockId hour minute
|
166
167
|
|
167
|
-
member private this.
|
168
|
+
member private this.RenderPropertyValue canonicalDataCase property =
|
168
169
|
this.RenderSutParameter (canonicalDataCase, property, Map.find property canonicalDataCase.Properties)
|
169
170
|
|
170
171
|
override __.PropertiesWithIdentifier _ = ["clock1"; "clock2"]
|
@@ -177,8 +178,8 @@ type Clock() =
|
|
177
178
|
override this.RenderArrange canonicalDataCase =
|
178
179
|
match canonicalDataCase.Property with
|
179
180
|
| "create" | "add" ->
|
180
|
-
let hour = this.
|
181
|
-
let minute = this.
|
181
|
+
let hour = this.RenderPropertyValue canonicalDataCase "hour"
|
182
|
+
let minute = this.RenderPropertyValue canonicalDataCase "minute"
|
182
183
|
[sprintf "let clock = create %s %s" hour minute]
|
183
184
|
| _ ->
|
184
185
|
base.RenderArrange canonicalDataCase
|
@@ -188,7 +189,7 @@ type Clock() =
|
|
188
189
|
| "create" ->
|
189
190
|
sprintf "display clock"
|
190
191
|
| "add" ->
|
191
|
-
this.
|
192
|
+
this.RenderPropertyValue canonicalDataCase "add"
|
192
193
|
|> sprintf "add %s clock |> display"
|
193
194
|
| "equal" ->
|
194
195
|
"clock1 = clock2"
|
@@ -250,7 +251,7 @@ type Dominoes() =
|
|
250
251
|
type Etl() =
|
251
252
|
inherit GeneratorExercise()
|
252
253
|
|
253
|
-
member __.
|
254
|
+
member __.FormatMap<'TKey, 'TValue> (value: obj) =
|
254
255
|
let input = value :?> JObject
|
255
256
|
let dict = input.ToObject<Collections.Generic.Dictionary<'TKey, 'TValue>>();
|
256
257
|
let formattedList =
|
@@ -263,9 +264,9 @@ type Etl() =
|
|
263
264
|
else
|
264
265
|
sprintf "%s |> Map.ofList" formattedList
|
265
266
|
|
266
|
-
override this.RenderInput (_, _, value) = this.
|
267
|
+
override this.RenderInput (_, _, value) = this.FormatMap<int, List<char>> value
|
267
268
|
|
268
|
-
override this.RenderExpected (_, _, value) = this.
|
269
|
+
override this.RenderExpected (_, _, value) = this.FormatMap<char, int> value
|
269
270
|
|
270
271
|
override this.PropertiesWithIdentifier canonicalDataCase = this.Properties canonicalDataCase
|
271
272
|
|
@@ -323,6 +324,35 @@ type Grains() =
|
|
323
324
|
| "-1" -> "Error \"Invalid input\""
|
324
325
|
| x -> sprintf "Ok %sUL" x
|
325
326
|
|
327
|
+
type Grep() =
|
328
|
+
inherit GeneratorExercise()
|
329
|
+
|
330
|
+
override this.PropertiesWithIdentifier canonicalDataCase = this.Properties canonicalDataCase
|
331
|
+
|
332
|
+
override __.RenderExpected (_, _, value) =
|
333
|
+
(value :?> JArray)
|
334
|
+
|> normalizeJArray
|
335
|
+
|> Seq.map formatValue
|
336
|
+
|> formatMultiLineListWithIndentation 3
|
337
|
+
|
338
|
+
override __.RenderSetup _ = renderPartialTemplate "Generators/GrepSetup" Map.empty<string, obj>
|
339
|
+
|
340
|
+
override __.RenderArrange canonicalDataCase =
|
341
|
+
base.RenderArrange canonicalDataCase @ [""; "createFiles() |> ignore"]
|
342
|
+
|
343
|
+
override __.IdentifierTypeAnnotation (canonicalDataCase, key, value) =
|
344
|
+
match key with
|
345
|
+
| "expected" ->
|
346
|
+
match value :?> JArray |> Seq.isEmpty with
|
347
|
+
| true -> Some "string list"
|
348
|
+
| false -> None
|
349
|
+
| _ ->
|
350
|
+
base.IdentifierTypeAnnotation(canonicalDataCase, key, value)
|
351
|
+
|
352
|
+
override __.AdditionalNamespaces = [typeof<System.IO.File>.Namespace]
|
353
|
+
|
354
|
+
override __.TestFileFormat = TestFileFormat.Class
|
355
|
+
|
326
356
|
type Hamming() =
|
327
357
|
inherit GeneratorExercise()
|
328
358
|
|
@@ -417,7 +447,7 @@ type Meetup() =
|
|
417
447
|
override __.PropertiesUsedAsSutParameter _ =
|
418
448
|
["year"; "month"; "dayofweek"; "week"]
|
419
449
|
|
420
|
-
override
|
450
|
+
override __.AdditionalNamespaces = [typeof<DateTime>.Namespace]
|
421
451
|
|
422
452
|
type Minesweeper() =
|
423
453
|
inherit GeneratorExercise()
|
@@ -447,7 +477,7 @@ type NthPrime() =
|
|
447
477
|
type NucleotideCount() =
|
448
478
|
inherit GeneratorExercise()
|
449
479
|
|
450
|
-
member __.
|
480
|
+
member __.FormatMap<'TKey, 'TValue> (value: obj) =
|
451
481
|
match Option.ofNonError value with
|
452
482
|
| None ->
|
453
483
|
"None"
|
@@ -464,7 +494,7 @@ type NucleotideCount() =
|
|
464
494
|
else
|
465
495
|
sprintf "%s |> Map.ofList |> Some" formattedList
|
466
496
|
|
467
|
-
override this.RenderExpected (_, _, value) = this.
|
497
|
+
override this.RenderExpected (_, _, value) = this.FormatMap<char, int> value
|
468
498
|
|
469
499
|
override this.PropertiesWithIdentifier canonicalDataCase = this.Properties canonicalDataCase
|
470
500
|
|
@@ -544,7 +574,7 @@ type PascalsTriangle() =
|
|
544
574
|
| false -> None
|
545
575
|
| _ -> base.IdentifierTypeAnnotation (canonicalDataCase, key, value)
|
546
576
|
|
547
|
-
override __.
|
577
|
+
override __.TestMethodBodyAssertTemplate _ = "AssertEqual"
|
548
578
|
|
549
579
|
type PerfectNumbers() =
|
550
580
|
inherit GeneratorExercise()
|
@@ -770,7 +800,7 @@ type RunLengthEncoding() =
|
|
770
800
|
| _ ->
|
771
801
|
base.RenderSut canonicalDataCase
|
772
802
|
|
773
|
-
override
|
803
|
+
override __.RenderTestMethodName canonicalDataCase =
|
774
804
|
match canonicalDataCase.Property with
|
775
805
|
| "consistency" ->
|
776
806
|
base.RenderTestMethodName canonicalDataCase
|
@@ -7,6 +7,7 @@ open FSharp.Reflection
|
|
7
7
|
open DotLiquid
|
8
8
|
open DotLiquid.FileSystems
|
9
9
|
open Formatting
|
10
|
+
open System.Collections
|
10
11
|
|
11
12
|
type OutputFilter() =
|
12
13
|
static member Format (input: string) = formatValue input
|
@@ -47,11 +48,17 @@ let rec private registerTypeTree templateDataType =
|
|
47
48
|
registrations.[templateDataType] <- true
|
48
49
|
for p in properties do registerTypeTree p.PropertyType
|
49
50
|
|
51
|
+
let private hashFromData (data: obj) =
|
52
|
+
match FSharpType.IsRecord (data.GetType()) with
|
53
|
+
| true -> Hash.FromAnonymousObject(data)
|
54
|
+
| false -> Hash.FromDictionary(data :?> IDictionary<string, obj>)
|
55
|
+
|
50
56
|
let renderInlineTemplate template data =
|
51
57
|
data.GetType() |> registerTypeTree
|
52
58
|
|
53
59
|
let parsedTemplate = Template.Parse template
|
54
|
-
|
60
|
+
let hash = hashFromData data
|
61
|
+
parsedTemplate.Render(hash)
|
55
62
|
|
56
63
|
let renderPartialTemplate templateName data =
|
57
64
|
let template = sprintf "{%% include \"%s\" %%}" templateName
|
@@ -0,0 +1,37 @@
|
|
1
|
+
let iliadFileName = "iliad.txt"
|
2
|
+
let iliadContents =
|
3
|
+
"""Achilles sing, O Goddess! Peleus' son;
|
4
|
+
His wrath pernicious, who ten thousand woes
|
5
|
+
Caused to Achaia's host, sent many a soul
|
6
|
+
Illustrious into Ades premature,
|
7
|
+
And Heroes gave (so stood the will of Jove)
|
8
|
+
To dogs and to all ravening fowls a prey,
|
9
|
+
When fierce dispute had separated once
|
10
|
+
The noble Chief Achilles from the son
|
11
|
+
Of Atreus, Agamemnon, King of men."""
|
12
|
+
|
13
|
+
let midsummerNightFileName = "midsummer-night.txt"
|
14
|
+
let midsummerNightContents =
|
15
|
+
"""I do entreat your grace to pardon me.
|
16
|
+
I know not by what power I am made bold,
|
17
|
+
Nor how it may concern my modesty,
|
18
|
+
In such a presence here to plead my thoughts;
|
19
|
+
But I beseech your grace that I may know
|
20
|
+
The worst that may befall me in this case,
|
21
|
+
If I refuse to wed Demetrius."""
|
22
|
+
|
23
|
+
let paradiseLostFileName = "paradise-lost.txt"
|
24
|
+
let paradiseLostContents =
|
25
|
+
"""Of Mans First Disobedience, and the Fruit
|
26
|
+
Of that Forbidden Tree, whose mortal tast
|
27
|
+
Brought Death into the World, and all our woe,
|
28
|
+
With loss of Eden, till one greater Man
|
29
|
+
Restore us, and regain the blissful Seat,
|
30
|
+
Sing Heav'nly Muse, that on the secret top
|
31
|
+
Of Oreb, or of Sinai, didst inspire
|
32
|
+
That Shepherd, who first taught the chosen Seed"""
|
33
|
+
|
34
|
+
let createFiles() =
|
35
|
+
File.WriteAllText(iliadFileName, iliadContents)
|
36
|
+
File.WriteAllText(midsummerNightFileName, midsummerNightContents)
|
37
|
+
File.WriteAllText(paradiseLostFileName, paradiseLostContents)
|
@@ -7,7 +7,13 @@ open {{ namespace }}
|
|
7
7
|
{%- endfor -%}
|
8
8
|
|
9
9
|
open {{ TestedModuleName }}
|
10
|
+
{%- if Setup != empty -%}
|
10
11
|
|
11
|
-
{
|
12
|
-
{
|
13
|
-
|
12
|
+
{{ Setup }}
|
13
|
+
{%- endif -%}
|
14
|
+
|
15
|
+
type {{ TestModuleName }}() =
|
16
|
+
|
17
|
+
{%- for method in Methods -%}
|
18
|
+
{{ method }}
|
19
|
+
{%- endfor -%}
|
File without changes
|
File without changes
|