From d048679dbbaaf28108638777be205b48df7984dc Mon Sep 17 00:00:00 2001 From: Parker Lougheed Date: Tue, 10 Aug 2021 18:10:38 -0500 Subject: [PATCH] Analyze and test more cheatsheet snippets --- .../bin/cheatsheet/collection_literals.dart | 27 ------ examples/misc/bin/cheatsheet/exceptions.dart | 53 ------------ examples/misc/bin/null_aware_operators.dart | 17 ---- .../cheatsheet/getter_compute.dart | 7 -- .../cheatsheet/getters_setters.dart | 6 -- .../cheatsheet}/optional_named_params.dart | 2 +- .../cheatsheet}/optional_positional_args.dart | 2 +- .../optional_positional_args2.dart | 2 +- .../misc/test/cheatsheet/arguments_test.dart | 44 ++++++++++ .../cheatsheet/arrow_functions_test.dart} | 14 +-- .../test/cheatsheet/collections_test.dart | 53 ++++++++++++ .../misc/test/cheatsheet/exceptions_test.dart | 86 +++++++++++++++++++ .../misc/test/cheatsheet/null_aware_test.dart | 48 +++++++++++ .../misc/test/cheatsheet/properties_test.dart | 27 ++++++ src/codelabs/dart-cheatsheet.md | 46 +++++----- 15 files changed, 293 insertions(+), 141 deletions(-) delete mode 100644 examples/misc/bin/cheatsheet/collection_literals.dart delete mode 100644 examples/misc/bin/cheatsheet/exceptions.dart delete mode 100644 examples/misc/bin/null_aware_operators.dart rename examples/misc/{bin => lib}/cheatsheet/getter_compute.dart (63%) rename examples/misc/{bin => lib}/cheatsheet/getters_setters.dart (66%) rename examples/misc/{bin => lib/cheatsheet}/optional_named_params.dart (92%) rename examples/misc/{bin => lib/cheatsheet}/optional_positional_args.dart (97%) rename examples/misc/{bin => lib/cheatsheet}/optional_positional_args2.dart (93%) create mode 100644 examples/misc/test/cheatsheet/arguments_test.dart rename examples/misc/{bin/cheatsheet/arrow_functions.dart => test/cheatsheet/arrow_functions_test.dart} (66%) create mode 100644 examples/misc/test/cheatsheet/collections_test.dart create mode 100644 examples/misc/test/cheatsheet/exceptions_test.dart create mode 100644 examples/misc/test/cheatsheet/null_aware_test.dart create mode 100644 examples/misc/test/cheatsheet/properties_test.dart diff --git a/examples/misc/bin/cheatsheet/collection_literals.dart b/examples/misc/bin/cheatsheet/collection_literals.dart deleted file mode 100644 index dec26f9005..0000000000 --- a/examples/misc/bin/cheatsheet/collection_literals.dart +++ /dev/null @@ -1,27 +0,0 @@ -// ignore_for_file: unused_local_variable - -void main() { - // #docregion collection-literals - final aListOfStrings = ['one', 'two', 'three']; - final aSetOfStrings = {'one', 'two', 'three'}; - final aMapOfStringsToInts = { - 'one': 1, - 'two': 2, - 'three': 3, - }; - // #enddocregion collection-literals - - // #docregion collection-literals-2 - final aListOfInts = []; - final aSetOfInts = {}; - final aMapOfIntToDouble = {}; - // #enddocregion collection-literals-2 - - // #docregion collection-literals-3 - final aListOfBaseType = [SubType(), SubType()]; - // #enddocregion collection-literals-3 -} - -class BaseType {} - -class SubType extends BaseType {} diff --git a/examples/misc/bin/cheatsheet/exceptions.dart b/examples/misc/bin/cheatsheet/exceptions.dart deleted file mode 100644 index 225e097fdf..0000000000 --- a/examples/misc/bin/cheatsheet/exceptions.dart +++ /dev/null @@ -1,53 +0,0 @@ -// ignore_for_file: dead_code, only_throw_errors - -void main() { - // #docregion try-on-catch - try { - breedMoreLlamas(); - } on OutOfLlamasException { - // A specific exception - buyMoreLlamas(); - } on Exception catch (e) { - // Anything else that is an exception - print('Unknown exception: $e'); - } catch (e) { - // No specified type, handles all - print('Something really unknown: $e'); - } - // #enddocregion try-on-catch - - // #docregion try-catch - try { - breedMoreLlamas(); - } catch (e) { - print('I was just trying to breed llamas!'); - rethrow; - } - // #enddocregion try-catch - - // #docregion try-catch-finally - try { - breedMoreLlamas(); - } catch (e) { - // ... handle exception ... - } finally { - // Always clean up, even if an exception is thrown. - cleanLlamaStalls(); - } - // #enddocregion try-catch-finally -} - -void cleanLlamaStalls() {} - -void breedMoreLlamas() {} - -void buyMoreLlamas() {} - -class OutOfLlamasException implements Exception {} - -void throwErrors() { - // #docregion simple-throws - throw Exception('Something bad happened.'); - throw 'Waaaaaaah!'; - // #enddocregion simple-throws -} diff --git a/examples/misc/bin/null_aware_operators.dart b/examples/misc/bin/null_aware_operators.dart deleted file mode 100644 index 9e58726b99..0000000000 --- a/examples/misc/bin/null_aware_operators.dart +++ /dev/null @@ -1,17 +0,0 @@ -// ignore_for_file: unnecessary_null_in_if_null_operators, dead_null_aware_expression - -void main() { -// #docregion null-aware-operators - int? a; // = null - a ??= 3; - print(a); // <-- Prints 3. - - a ??= 5; - print(a); // <-- Still prints 3. -// #enddocregion null-aware-operators - -// #docregion null-aware-operators-2 - print(1 ?? 3); // <-- Prints 1. - print(null ?? 12); // <-- Prints 12. -// #enddocregion null-aware-operators-2 -} diff --git a/examples/misc/bin/cheatsheet/getter_compute.dart b/examples/misc/lib/cheatsheet/getter_compute.dart similarity index 63% rename from examples/misc/bin/cheatsheet/getter_compute.dart rename to examples/misc/lib/cheatsheet/getter_compute.dart index f71e355e51..c350b55395 100644 --- a/examples/misc/bin/cheatsheet/getter_compute.dart +++ b/examples/misc/lib/cheatsheet/getter_compute.dart @@ -12,10 +12,3 @@ class MyClass { } } // #enddocregion - -void main() { - MyClass _class = MyClass(); - _class.addValue(5); - _class.addValue(7); - print(_class.count.toString()); -} diff --git a/examples/misc/bin/cheatsheet/getters_setters.dart b/examples/misc/lib/cheatsheet/getters_setters.dart similarity index 66% rename from examples/misc/bin/cheatsheet/getters_setters.dart rename to examples/misc/lib/cheatsheet/getters_setters.dart index 6f3cc73962..a5e952fef8 100644 --- a/examples/misc/bin/cheatsheet/getters_setters.dart +++ b/examples/misc/lib/cheatsheet/getters_setters.dart @@ -11,9 +11,3 @@ class MyClass { } } // #enddocregion - -void main() { - MyClass _class = MyClass(); - _class.aProperty = 5; - print(_class.aProperty); -} diff --git a/examples/misc/bin/optional_named_params.dart b/examples/misc/lib/cheatsheet/optional_named_params.dart similarity index 92% rename from examples/misc/bin/optional_named_params.dart rename to examples/misc/lib/cheatsheet/optional_named_params.dart index 2d3131da9b..a9e68449d9 100644 --- a/examples/misc/bin/optional_named_params.dart +++ b/examples/misc/lib/cheatsheet/optional_named_params.dart @@ -4,7 +4,7 @@ void printName(String firstName, String lastName, {String? suffix}) { } // #enddocregion -void main() { +void printNameTest() { // #docregion printName('Avinash', 'Gupta'); printName('Poshmeister', 'Moneybuckets', suffix: 'IV'); diff --git a/examples/misc/bin/optional_positional_args.dart b/examples/misc/lib/cheatsheet/optional_positional_args.dart similarity index 97% rename from examples/misc/bin/optional_positional_args.dart rename to examples/misc/lib/cheatsheet/optional_positional_args.dart index 705eb16769..6d6087188e 100644 --- a/examples/misc/bin/optional_positional_args.dart +++ b/examples/misc/lib/cheatsheet/optional_positional_args.dart @@ -15,7 +15,7 @@ int sumUp(int a, int b, int c) { } // #enddocregion optional-positional-args -void main() { +void mainTest() { // #docregion optional-positional-args int total = sumUp(1, 2, 3); // #enddocregion optional-positional-args diff --git a/examples/misc/bin/optional_positional_args2.dart b/examples/misc/lib/cheatsheet/optional_positional_args2.dart similarity index 93% rename from examples/misc/bin/optional_positional_args2.dart rename to examples/misc/lib/cheatsheet/optional_positional_args2.dart index defed9e8a1..8ade9e9bb3 100644 --- a/examples/misc/bin/optional_positional_args2.dart +++ b/examples/misc/lib/cheatsheet/optional_positional_args2.dart @@ -6,7 +6,7 @@ int sumUpToFive(int a, [int b = 2, int c = 3, int d = 4, int e = 5]) { } // #enddocregion -void main() { +void mainTest() { // #docregion int newTotal = sumUpToFive(1); print(newTotal); // <-- prints 15 diff --git a/examples/misc/test/cheatsheet/arguments_test.dart b/examples/misc/test/cheatsheet/arguments_test.dart new file mode 100644 index 0000000000..5e31340a31 --- /dev/null +++ b/examples/misc/test/cheatsheet/arguments_test.dart @@ -0,0 +1,44 @@ +import 'package:examples/cheatsheet/optional_named_params.dart'; +import 'package:examples/cheatsheet/optional_positional_args.dart' as optionalArgs; +import 'package:examples/cheatsheet/optional_positional_args2.dart' as defaultedArgs; +import 'package:test/test.dart'; + +void main() { + test('print_name', () { + expect(() { + printNameTest(); + }, prints('Avinash Gupta \nPoshmeister Moneybuckets IV\n')); + }); + + test('print_name_default', () { + // #docregion defaulted-suffix + void printName(String firstName, String lastName, {String suffix = ''}) { + print('$firstName $lastName $suffix'); + } + // #enddocregion defaulted-suffix + + expect(() { + printName('Dash', 'Dartisan', suffix: 'III'); + }, prints('Dash Dartisan III\n')); + + expect(() { + printName('Dash', 'Dartisan'); + }, prints('Dash Dartisan \n')); + }); + + test('optional_positional_args', () { + expect(() { + optionalArgs.mainTest(); + }, prints('6\n3\n15\n')); + + expect(optionalArgs.sumUpToFive(1, 4, 7), equals(12)); + }); + + test('optional_positional_args_defaulted', () { + expect(() { + defaultedArgs.mainTest(); + }, prints('15\n')); + + expect(defaultedArgs.sumUpToFive(1, 1), equals(14)); + }); +} diff --git a/examples/misc/bin/cheatsheet/arrow_functions.dart b/examples/misc/test/cheatsheet/arrow_functions_test.dart similarity index 66% rename from examples/misc/bin/cheatsheet/arrow_functions.dart rename to examples/misc/test/cheatsheet/arrow_functions_test.dart index 49a86f85dc..5d5d089a7d 100644 --- a/examples/misc/bin/cheatsheet/arrow_functions.dart +++ b/examples/misc/test/cheatsheet/arrow_functions_test.dart @@ -1,19 +1,23 @@ -// ignore_for_file: unused_local_variable +import 'package:test/test.dart'; void main() { const aListOfStrings = ['a', 'b', 'c']; - { + test('has_empty_long', () { // #docregion has-empty-long bool hasEmpty = aListOfStrings.any((s) { return s.isEmpty; }); // #enddocregion has-empty-long - } - { + expect(hasEmpty, isFalse); + }); + + test('has_empty_short', () { // #docregion has-empty-short bool hasEmpty = aListOfStrings.any((s) => s.isEmpty); // #enddocregion has-empty-short - } + + expect(hasEmpty, isFalse); + }); } diff --git a/examples/misc/test/cheatsheet/collections_test.dart b/examples/misc/test/cheatsheet/collections_test.dart new file mode 100644 index 0000000000..47df9b5530 --- /dev/null +++ b/examples/misc/test/cheatsheet/collections_test.dart @@ -0,0 +1,53 @@ +import 'package:test/test.dart'; + +void main() { + test('collection_literals_inferred', () { + // #docregion collection-literals-inferred + final aListOfStrings = ['one', 'two', 'three']; + final aSetOfStrings = {'one', 'two', 'three'}; + final aMapOfStringsToInts = { + 'one': 1, + 'two': 2, + 'three': 3, + }; + // #enddocregion collection-literals-inferred + + expect(aListOfStrings, isA>()); + expect(aListOfStrings[1], equals('two')); + + expect(aSetOfStrings, isA>()); + expect(aSetOfStrings, contains('two')); + + expect(aMapOfStringsToInts, isA>()); + expect(aMapOfStringsToInts['two'], equals(2)); + }); + + test('collection_literals_specified', () { + // #docregion collection-literals-specified + final aListOfInts = []; + final aSetOfInts = {}; + final aMapOfIntToDouble = {}; + // #enddocregion collection-literals-specified + + expect(aListOfInts, isA>()); + + expect(aSetOfInts, isA>()); + + expect(aMapOfIntToDouble, isA>()); + }); + + test('collection_literals_subtypes', () { + // #docregion collection-literals-subtypes + final aListOfBaseType = [SubType(), SubType()]; + // #enddocregion collection-literals-subtypes + + expect(aListOfBaseType, isA>()); + + expect( + aListOfBaseType, containsAllInOrder([isA(), isA()])); + }); +} + +class BaseType {} + +class SubType extends BaseType {} diff --git a/examples/misc/test/cheatsheet/exceptions_test.dart b/examples/misc/test/cheatsheet/exceptions_test.dart new file mode 100644 index 0000000000..03de3c5820 --- /dev/null +++ b/examples/misc/test/cheatsheet/exceptions_test.dart @@ -0,0 +1,86 @@ +// ignore_for_file: dead_code + +import 'package:test/test.dart'; + +void main() { + test('try_on_catch', () { + expect(() { + // #docregion try-on-catch + try { + breedMoreLlamas(); + } on OutOfLlamasException { + // A specific exception + buyMoreLlamas(); + } on Exception catch (e) { + // Anything else that is an exception + print('Unknown exception: $e'); + } catch (e) { + // No specified type, handles all + print('Something really unknown: $e'); + } + // #enddocregion try-on-catch + }, prints('Bought more llamas.\n')); + }); + + test('simple_throws', () { + void throwErrors() { + // #docregion simple-throws + throw Exception('Something bad happened.'); + throw 'Waaaaaaah!'; + // #enddocregion simple-throws + } + + expect(throwErrors, throwsException); + }); + + test('try_catch', () { + expect(() { + expect(() { + // #docregion try-catch + try { + breedMoreLlamas(); + } catch (e) { + print('I was just trying to breed llamas!'); + rethrow; + } + // #enddocregion try-catch + }, throwsA(isA())); + }, prints('I was just trying to breed llamas!\n')); + }); + + test('try_catch_finally', () { + expect(() { + // #docregion try-catch-finally + try { + breedMoreLlamas(); + } catch (e) { + // ... handle exception ... + } finally { + // Always clean up, even if an exception is thrown. + cleanLlamaStalls(); + } + // #enddocregion try-catch-finally + }, prints('Cleaned llama stalls.\n')); + }); +} + +void cleanLlamaStalls() { + print('Cleaned llama stalls.'); +} + +void breedMoreLlamas() { + throw OutOfLlamasException(); +} + +void buyMoreLlamas() { + print('Bought more llamas.'); +} + +class OutOfLlamasException implements Exception {} + +void throwErrors() { + // #docregion simple-throws + throw Exception('Something bad happened.'); + throw 'Waaaaaaah!'; + // #enddocregion simple-throws +} diff --git a/examples/misc/test/cheatsheet/null_aware_test.dart b/examples/misc/test/cheatsheet/null_aware_test.dart new file mode 100644 index 0000000000..003d88d296 --- /dev/null +++ b/examples/misc/test/cheatsheet/null_aware_test.dart @@ -0,0 +1,48 @@ +// ignore_for_file: unused_local_variable, unnecessary_null_in_if_null_operators, dead_null_aware_expression + +import 'package:test/test.dart'; + +void main() { + test('null_aware_operators', () { + void nullAware() { + // #docregion null-aware-operators + int? a; // = null + a ??= 3; + print(a); // <-- Prints 3. + + a ??= 5; + print(a); // <-- Still prints 3. + // #enddocregion null-aware-operators + + // #docregion null-aware-operators-2 + print(1 ?? 3); // <-- Prints 1. + print(null ?? 12); // <-- Prints 12. + // #enddocregion null-aware-operators-2 + } + + expect(nullAware, prints('3\n3\n1\n12\n')); + }); + + test('conditional_property_access', () { + dynamic myObject; + dynamic result; + + // #docregion conditional-property-access + result = myObject?.someProperty; + // #enddocregion conditional-property-access + + expect(result, isNull); + + // #docregion conditional-property-access-equivalent + result = (myObject != null) ? myObject.someProperty : null; + // #enddocregion conditional-property-access-equivalent + + expect(result, isNull); + + // #docregion conditional-property-access-multiple + result = myObject?.someProperty?.someMethod(); + // #enddocregion conditional-property-access-multiple + + expect(result, isNull); + }); +} diff --git a/examples/misc/test/cheatsheet/properties_test.dart b/examples/misc/test/cheatsheet/properties_test.dart new file mode 100644 index 0000000000..17a7d89f08 --- /dev/null +++ b/examples/misc/test/cheatsheet/properties_test.dart @@ -0,0 +1,27 @@ +import 'package:examples/cheatsheet/getter_compute.dart' as getters_compute; +import 'package:examples/cheatsheet/getters_setters.dart' as getters_setters; +import 'package:test/test.dart'; + +void main() { + test('getters_setters', () { + getters_setters.MyClass _class = getters_setters.MyClass(); + _class.aProperty = 5; + + expect(_class.aProperty, equals(5)); + + _class.aProperty = -10; + + expect(_class.aProperty, equals(5)); + }); + + test('getter_compute', () { + getters_compute.MyClass _class = getters_compute.MyClass(); + _class.addValue(5); + + expect(_class.count, equals(1)); + + _class.addValue(7); + + expect(_class.count, equals(2)); + }); +} \ No newline at end of file diff --git a/src/codelabs/dart-cheatsheet.md b/src/codelabs/dart-cheatsheet.md index 15181ce154..7de8e4594e 100644 --- a/src/codelabs/dart-cheatsheet.md +++ b/src/codelabs/dart-cheatsheet.md @@ -168,11 +168,7 @@ Dart offers some handy operators for dealing with values that might be null. One `??=` assignment operator, which assigns a value to a variable only if that variable is currently null: -{% comment %} -TBD: Make this and all non-trivial snippets testable. -{% endcomment %} - - + ```dart int? a; // = null a ??= 3; @@ -187,7 +183,7 @@ which returns the expression on its left unless that expression's value is null, in which case it evaluates and returns the expression on its right: - + ```dart print(1 ?? 3); // <-- Prints 1. print(null ?? 12); // <-- Prints 12. @@ -263,18 +259,21 @@ and then give it a try. To guard access to a property or method of an object that might be null, put a question mark (`?`) before the dot (`.`): + ```dart myObject?.someProperty ``` The preceding code is equivalent to the following: + ```dart (myObject != null) ? myObject.someProperty : null ``` You can chain multiple uses of `?.` together in a single expression: + ```dart myObject?.someProperty?.someMethod() ``` @@ -348,7 +347,7 @@ you could do it like this: str?.toLowerCase() Dart has built-in support for lists, maps, and sets. You can create them using literals: - + ```dart final aListOfStrings = ['one', 'two', 'three']; final aSetOfStrings = {'one', 'two', 'three'}; @@ -365,7 +364,7 @@ In this case, the inferred types are `List`, Or you can specify the type yourself: - + ```dart final aListOfInts = []; final aSetOfInts = {}; @@ -375,7 +374,7 @@ final aMapOfIntToDouble = {}; Specifying types is handy when you initialize a list with contents of a subtype, but still want the list to be `List`: - + ```dart final aListOfBaseType = [SubType(), SubType()]; ``` @@ -491,7 +490,7 @@ expression to its right and returns its value. For example, consider this call to the `List` class's `any()` method: - + ```dart bool hasEmpty = aListOfStrings.any((s) { return s.isEmpty; @@ -500,7 +499,7 @@ bool hasEmpty = aListOfStrings.any((s) { Here’s a simpler way to write that code: - + ```dart bool hasEmpty = aListOfStrings.any((s) => s.isEmpty); ``` @@ -769,7 +768,7 @@ than a simple field allows. For example, you can make sure a property's value is valid: - + ```dart class MyClass { int _aProperty = 0; @@ -786,7 +785,7 @@ class MyClass { You can also use a getter to define a computed property: - + ```dart class MyClass { final List _values = []; @@ -916,7 +915,7 @@ with a function you give it Dart has two kinds of function parameters: positional and named. Positional parameters are the kind you're likely familiar with: - + ```dart int sumUp(int a, int b, int c) { return a + b + c; @@ -927,7 +926,7 @@ int sumUp(int a, int b, int c) { With Dart, you can make these positional parameters optional by wrapping them in brackets: - + ```dart int sumUpToFive(int a, [int? b, int? c, int? d, int? e]) { int sum = a; @@ -946,7 +945,7 @@ Optional positional parameters are always last in a function's parameter list. Their default value is null unless you provide another default value: - + ```dart int sumUpToFive(int a, [int b = 2, int c = 3, int d = 4, int e = 5]) { // ··· @@ -1052,7 +1051,7 @@ before you add them to the final string. Using a curly brace syntax, you can define optional parameters that have names. - + ```dart void printName(String firstName, String lastName, {String? suffix}) { print('$firstName $lastName ${suffix ?? ''}'); @@ -1073,11 +1072,12 @@ or mark the parameter as `required` (as shown in the [constructor section](#using-this-in-a-constructor)). -{% prettify dart tag=pre+code %} + +```dart void printName(String firstName, String lastName, {String suffix[! = ''!]}) { print('$firstName $lastName $suffix'); } -{% endprettify %} +``` A function can't have both optional positional and optional named parameters. @@ -1206,7 +1206,7 @@ any exceptions. Dart provides `Exception` and `Error` types, but you're allowed to throw any non-null object: - + ```dart throw Exception('Something bad happened.'); throw 'Waaaaaaah!'; @@ -1214,7 +1214,7 @@ throw 'Waaaaaaah!'; Use the `try`, `on`, and `catch` keywords when handling exceptions: - + ```dart try { breedMoreLlamas(); @@ -1237,7 +1237,7 @@ and the `catch` keyword to get a reference to the exception object. If you can't completely handle the exception, use the `rethrow` keyword to propagate the exception: - + ```dart try { breedMoreLlamas(); @@ -1250,7 +1250,7 @@ try { To execute code whether or not an exception is thrown, use `finally`: - + ```dart try { breedMoreLlamas();