From 92f388ff9e429387ae7f6b4e985ca97461e9490a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Nov 2022 04:46:25 -0600 Subject: [PATCH 01/32] Bump github/codeql-action from 2.1.30 to 2.1.31 (#4353) --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 8332adb72..688839230 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -33,7 +33,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@18fe527fa8b29f134bb91f32f1a5dc5abb15ed7f + uses: github/codeql-action/init@c3b6fce4ee2ca25bc1066aa3bf73962fda0e8898 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -44,7 +44,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@18fe527fa8b29f134bb91f32f1a5dc5abb15ed7f + uses: github/codeql-action/autobuild@c3b6fce4ee2ca25bc1066aa3bf73962fda0e8898 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -58,4 +58,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@18fe527fa8b29f134bb91f32f1a5dc5abb15ed7f + uses: github/codeql-action/analyze@c3b6fce4ee2ca25bc1066aa3bf73962fda0e8898 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index d9b73e2be..5aef51b2e 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -49,6 +49,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@18fe527fa8b29f134bb91f32f1a5dc5abb15ed7f + uses: github/codeql-action/upload-sarif@c3b6fce4ee2ca25bc1066aa3bf73962fda0e8898 with: sarif_file: results.sarif From 6deb7192f7229ace7c0b2105013c0be32d44b8ea Mon Sep 17 00:00:00 2001 From: Parker Lougheed Date: Tue, 8 Nov 2022 11:06:56 -0600 Subject: [PATCH 02/32] Only add a tag to JS code where include-lang is specified (#4346) --- src/_sass/main.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_sass/main.scss b/src/_sass/main.scss index 5f969bf35..3aad7b18b 100644 --- a/src/_sass/main.scss +++ b/src/_sass/main.scss @@ -489,7 +489,7 @@ li.card { @include dart-style-for(runtime-success, $alert-success-bg, $alert-success-fg, '\2714 runtime: success'); @include dart-style-for(runtime-fail, $alert-danger-bg, $alert-danger-fg, '\2717 runtime: error'); @include dart-style-for('include-lang.language-dart', $pre-bg, $brand-primary, 'Dart'); -@include dart-style-for(language-js, $pre-bg, #f1a85a, 'JavaScript'); +@include dart-style-for('include-lang.language-js', $pre-bg, #f1a85a, 'JavaScript'); .muted { color: $gray; From e96d5a911f6f95aa44ae550dbd16b54fad09d28f Mon Sep 17 00:00:00 2001 From: Parker Lougheed Date: Tue, 8 Nov 2022 15:40:05 -0600 Subject: [PATCH 03/32] Adjust and move Effective Dart's linter mention (#4345) Contributes to #1319 Co-authored-by: Anthony Sansone --- src/_guides/language/effective-dart/index.md | 29 ++++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/_guides/language/effective-dart/index.md b/src/_guides/language/effective-dart/index.md index ced91185f..471c7382f 100644 --- a/src/_guides/language/effective-dart/index.md +++ b/src/_guides/language/effective-dart/index.md @@ -33,18 +33,6 @@ write consistent, robust, fast code too. There are two overarching themes: [code golf]: https://en.wikipedia.org/wiki/Code_golf -The Dart analyzer has a linter to help you write good, consistent code. -If a linter rule exists that can help you follow a guideline, -then the guideline links to that rule. Here's an example: - -{% include linter-rule-mention.md rule="prefer_collection_literals" %} - -For help on -[enabling linter rules](/guides/language/analysis-options#enabling-linter-rules), -see the documentation for -[customizing static analysis](/guides/language/analysis-options). - - ## The guides We split the guidelines into a few separate pages for easy digestion: @@ -107,6 +95,23 @@ your laces tied correctly. Things aren't that bad. Most of the guidelines here are common sense and we're all reasonable people. The goal, as always, is nice, readable and maintainable code. +The Dart analyzer provides a linter +to help you write good, consistent code +that follows these and other guidelines. +If one or more [linter rules][lints] exist +that can help you follow a guideline +then the guideline links to those rules. +The links use the following format: + +{% include linter-rule-mention.md rule="unnecessary_getters_setters" %} + +To learn how to use the linter, +see [Enabling linter rules][] +and the list of [linter rules][lints]. + +[Enabling linter rules]: /guides/language/analysis-options#enabling-linter-rules +[lints]: /tools/linter-rules + ## Glossary To keep the guidelines brief, we use a few shorthand terms to refer to different From 4efe1dc2db4d410651d11a8182f5fc1452734616 Mon Sep 17 00:00:00 2001 From: Parker Lougheed Date: Tue, 8 Nov 2022 23:00:13 -0600 Subject: [PATCH 04/32] Document specifying a file path when activating a package (#4356) Fixes https://github.com/dart-lang/site-www/issues/4166 Co-authored-by: Anthony Sansone --- src/tools/pub/cmd/pub-global.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/tools/pub/cmd/pub-global.md b/src/tools/pub/cmd/pub-global.md index 22111abbd..c7aa025f9 100644 --- a/src/tools/pub/cmd/pub-global.md +++ b/src/tools/pub/cmd/pub-global.md @@ -73,6 +73,15 @@ $ dart pub global activate --source git https://github.com/dart-lang/async_await $ dart pub global activate -sgit https://github.com/dart-lang/async_await.git ``` +Pub expects to find the package in the root of the Git repository. +To specify a different location, +use the `--git-path` option with +a path relative to the repository root: + +```terminal +$ dart pub global activate -sgit https://github.com/dart-lang/http.git --git-path pkgs/http/ +``` + ### Activating a package on your local machine ```terminal From 659fc2df08ec498a654a32bdc22ab1a16de8d0fb Mon Sep 17 00:00:00 2001 From: Alexander Thomas Date: Wed, 9 Nov 2022 16:35:44 +0000 Subject: [PATCH 05/32] Add macOS 13 Ventura and remove Catalina support (#4316) Co-authored-by: Anthony Sansone --- src/get-dart/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/get-dart/index.md b/src/get-dart/index.md index de2edb975..4e632cec2 100644 --- a/src/get-dart/index.md +++ b/src/get-dart/index.md @@ -75,10 +75,10 @@ The Dart SDK is supported on Windows, Linux, and macOS. ### macOS * **Supported versions:** Latest three major versions. - As of November 2021, the following versions are supported: - - macOS 10.15 (Catalina) +Dart supports the following macOS versions as of November 2022: - macOS 11 (Big Sur) - macOS 12 (Monterey) + - macOS 13 (Ventura) * **Supported architectures:** x64, ARM64. ## About release channels and version strings {#release-channels} From 537e4509f9e6d4c8169e086d09f81c45bfefccf8 Mon Sep 17 00:00:00 2001 From: Parker Lougheed Date: Wed, 9 Nov 2022 23:49:49 -0600 Subject: [PATCH 06/32] Update linter rules to release 1.30 (#4358) From 1.30 changelog: - New lint: `enable_null_safety` - New lint: `library_annotations` - Miscellaneous documentation improvements --- src/_data/linter_rules.json | 48 +++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/src/_data/linter_rules.json b/src/_data/linter_rules.json index 30d41171d..c6ea03c0e 100644 --- a/src/_data/linter_rules.json +++ b/src/_data/linter_rules.json @@ -7,7 +7,7 @@ "incompatible": [], "sets": [], "fixStatus": "hasFix", - "details": "**DO** avoid relative imports for files in `lib/`.\n\nWhen mixing relative and absolute imports it's possible to create confusion\nwhere the same member gets imported in two different ways. One way to avoid\nthat is to ensure you consistently use absolute imports for files withing the\n`lib/` directory.\n\nThis is the opposite of 'prefer_relative_imports'.\n\nYou can also use 'avoid_relative_lib_imports' to disallow relative imports of\nfiles within `lib/` directory outside of it (for example `test/`).\n\n**GOOD:**\n\n```dart\nimport 'package:foo/bar.dart';\n\nimport 'package:foo/baz.dart';\n\nimport 'package:foo/src/baz.dart';\n...\n```\n\n**BAD:**\n\n```dart\nimport 'baz.dart';\n\nimport 'src/bag.dart'\n\nimport '../lib/baz.dart';\n\n...\n```\n\n", + "details": "**DO** avoid relative imports for files in `lib/`.\n\nWhen mixing relative and absolute imports it's possible to create confusion\nwhere the same member gets imported in two different ways. One way to avoid\nthat is to ensure you consistently use absolute imports for files within the\n`lib/` directory.\n\nThis is the opposite of 'prefer_relative_imports'.\n\nYou can also use 'avoid_relative_lib_imports' to disallow relative imports of\nfiles within `lib/` directory outside of it (for example `test/`).\n\n**GOOD:**\n\n```dart\nimport 'package:foo/bar.dart';\n\nimport 'package:foo/baz.dart';\n\nimport 'package:foo/src/baz.dart';\n...\n```\n\n**BAD:**\n\n```dart\nimport 'baz.dart';\n\nimport 'src/bag.dart'\n\nimport '../lib/baz.dart';\n\n...\n```\n\n", "sinceDartSdk": "2.10.0", "sinceLinter": "0.1.118" }, @@ -166,7 +166,7 @@ "maturity": "stable", "incompatible": [], "sets": [], - "fixStatus": "unregistered", + "fixStatus": "needsEvaluation", "details": "**DON'T** invoke certain collection method with an argument with an unrelated\ntype.\n\nDoing this will invoke `==` on the collection's elements and most likely will\nreturn `false`.\n\nAn argument passed to a collection method should relate to the collection type\nas follows:\n\n* an argument to `Iterable.contains` should be related to `E`\n* an argument to `List.remove` should be related to `E`\n* an argument to `Map.containsKey` should be related to `K`\n* an argument to `Map.containsValue` should be related to `V`\n* an argument to `Map.remove` should be related to `K`\n* an argument to `Map.[]` should be related to `K`\n* an argument to `Queue.remove` should be related to `E`\n* an argument to `Set.containsAll` should be related to `Iterable`\n* an argument to `Set.difference` should be related to `Set`\n* an argument to `Set.intersection` should be related to `Set`\n* an argument to `Set.lookup` should be related to `E`\n* an argument to `Set.remove` should be related to `E`\n* an argument to `Set.removeAll` should be related to `Iterable`\n* an argument to `Set.retainAll` should be related to `Iterable`\n\n**BAD:**\n```dart\nvoid someFunction() {\n var list = [];\n if (list.contains('1')) print('someFunction'); // LINT\n}\n```\n\n**BAD:**\n```dart\nvoid someFunction() {\n var set = {};\n set.removeAll({'1'}); // LINT\n}\n```\n\n**GOOD:**\n```dart\nvoid someFunction() {\n var list = [];\n if (list.contains(1)) print('someFunction'); // OK\n}\n```\n\n**GOOD:**\n```dart\nvoid someFunction() {\n var set = {};\n set.removeAll({1}); // OK\n}\n```\n\n", "sinceDartSdk": "Unreleased", "sinceLinter": "1.29.0" @@ -359,7 +359,7 @@ "incompatible": [], "sets": [], "fixStatus": "hasFix", - "details": "**PREFER** relative imports for files in `lib/`.\n\nWhen mixing relative and absolute imports it's possible to create confusion\nwhere the same member gets imported in two different ways. One way to avoid\nthat is to ensure you consistently use relative imports for files withing the\n`lib/` directory.\n\n**GOOD:**\n\n```dart\nimport 'bar.dart';\n```\n\n**BAD:**\n\n```dart\nimport 'package:my_package/bar.dart';\n```\n\n", + "details": "**PREFER** relative imports for files in `lib/`.\n\nWhen mixing relative and absolute imports it's possible to create confusion\nwhere the same member gets imported in two different ways. One way to avoid\nthat is to ensure you consistently use relative imports for files within the\n`lib/` directory.\n\n**GOOD:**\n\n```dart\nimport 'bar.dart';\n```\n\n**BAD:**\n\n```dart\nimport 'package:my_package/bar.dart';\n```\n\n", "sinceDartSdk": "2.6.0", "sinceLinter": "0.1.99" }, @@ -794,7 +794,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "From [effective dart](https://dart.dev/guides/language/effective-dart/usage#dont-explicitly-initialize-variables-to-null):\n\n**DON'T** explicitly initialize variables to null.\n\nIn Dart, a variable or field that is not explicitly initialized automatically\ngets initialized to null. This is reliably specified by the language. There's\nno concept of \"uninitialized memory\" in Dart. Adding `= null` is redundant and\nunneeded.\n\n**GOOD:**\n```dart\nint _nextId;\n\nclass LazyId {\n int _id;\n\n int get id {\n if (_nextId == null) _nextId = 0;\n if (_id == null) _id = _nextId++;\n\n return _id;\n }\n}\n```\n\n**BAD:**\n```dart\nint _nextId = null;\n\nclass LazyId {\n int _id = null;\n\n int get id {\n if (_nextId == null) _nextId = 0;\n if (_id == null) _id = _nextId++;\n\n return _id;\n }\n}\n```\n\n", + "details": "From [Effective Dart](https://dart.dev/guides/language/effective-dart/usage#dont-explicitly-initialize-variables-to-null):\n\n**DON'T** explicitly initialize variables to null.\n\nIn Dart, a variable or field that is not explicitly initialized automatically\ngets initialized to null. This is reliably specified by the language. There's\nno concept of \"uninitialized memory\" in Dart. Adding `= null` is redundant and\nunneeded.\n\n**GOOD:**\n```dart\nint _nextId;\n\nclass LazyId {\n int _id;\n\n int get id {\n if (_nextId == null) _nextId = 0;\n if (_id == null) _id = _nextId++;\n\n return _id;\n }\n}\n```\n\n**BAD:**\n```dart\nint _nextId = null;\n\nclass LazyId {\n int _id = null;\n\n int get id {\n if (_nextId == null) _nextId = 0;\n if (_id == null) _id = _nextId++;\n\n return _id;\n }\n}\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.11" }, @@ -1171,7 +1171,7 @@ "maturity": "stable", "incompatible": [], "sets": [], - "fixStatus": "unregistered", + "fixStatus": "needsEvaluation", "details": "Attach library doc comments (with `///`) to library directives, rather than\nleaving them dangling near the top of a library.\n\n**BAD:**\n```dart\n/// This is a great library.\nimport 'package:math';\n```\n\n```dart\n/// This is a great library.\n\nclass C {}\n```\n\n**GOOD:**\n```dart\n/// This is a great library.\nlibrary;\n\nimport 'package:math';\n\nclass C {}\n```\n\n**NOTE:** An unnamed library, like `library;` above, is only supported in Dart\n2.19 and later. Code which might run in earlier versions of Dart will need to\nprovide a name in the `library` directive.\n", "sinceDartSdk": "Unreleased", "sinceLinter": "1.29.0" @@ -1196,7 +1196,7 @@ "incompatible": [], "sets": [], "fixStatus": "hasFix", - "details": "**DO** follow the conventions in the \n[Effective Dart Guide](https://dart.dev/guides/language/effective-dart/style#ordering)\n\n**DO** place `dart:` imports before other imports.\n\n**BAD:**\n```dart\nimport 'package:bar/bar.dart';\nimport 'package:foo/foo.dart';\n\nimport 'dart:async'; // LINT\nimport 'dart:html'; // LINT\n```\n\n**BAD:**\n```dart\nimport 'dart:html'; // OK\nimport 'package:bar/bar.dart';\n\nimport 'dart:async'; // LINT\nimport 'package:foo/foo.dart';\n```\n\n**GOOD:**\n```dart\nimport 'dart:async'; // OK\nimport 'dart:html'; // OK\n\nimport 'package:bar/bar.dart';\nimport 'package:foo/foo.dart';\n```\n\n**DO** place `package:` imports before relative imports.\n\n**BAD:**\n```dart\nimport 'a.dart';\nimport 'b.dart';\n\nimport 'package:bar/bar.dart'; // LINT\nimport 'package:foo/foo.dart'; // LINT\n```\n\n**BAD:**\n```dart\nimport 'package:bar/bar.dart'; // OK\nimport 'a.dart';\n\nimport 'package:foo/foo.dart'; // LINT\nimport 'b.dart';\n```\n\n**GOOD:**\n```dart\nimport 'package:bar/bar.dart'; // OK\nimport 'package:foo/foo.dart'; // OK\n\nimport 'a.dart';\nimport 'b.dart';\n```\n\n**DO** specify exports in a separate section after all imports.\n\n**BAD:**\n```dart\nimport 'src/error.dart';\nexport 'src/error.dart'; // LINT\nimport 'src/string_source.dart';\n```\n\n**GOOD:**\n```dart\nimport 'src/error.dart';\nimport 'src/string_source.dart';\n\nexport 'src/error.dart'; // OK\n```\n\n**DO** sort sections alphabetically.\n\n**BAD:**\n```dart\nimport 'package:foo/bar.dart'; // OK\nimport 'package:bar/bar.dart'; // LINT\n\nimport 'a/b.dart'; // OK\nimport 'a.dart'; // LINT\n```\n\n**GOOD:**\n```dart\nimport 'package:bar/bar.dart'; // OK\nimport 'package:foo/bar.dart'; // OK\n\nimport 'a.dart'; // OK\nimport 'a/b.dart'; // OK\n```\n", + "details": "**DO** follow the directive ordering conventions in\n[Effective Dart](https://dart.dev/guides/language/effective-dart/style#ordering):\n\n**DO** place `dart:` imports before other imports.\n\n**BAD:**\n```dart\nimport 'package:bar/bar.dart';\nimport 'package:foo/foo.dart';\n\nimport 'dart:async'; // LINT\nimport 'dart:html'; // LINT\n```\n\n**BAD:**\n```dart\nimport 'dart:html'; // OK\nimport 'package:bar/bar.dart';\n\nimport 'dart:async'; // LINT\nimport 'package:foo/foo.dart';\n```\n\n**GOOD:**\n```dart\nimport 'dart:async'; // OK\nimport 'dart:html'; // OK\n\nimport 'package:bar/bar.dart';\nimport 'package:foo/foo.dart';\n```\n\n**DO** place `package:` imports before relative imports.\n\n**BAD:**\n```dart\nimport 'a.dart';\nimport 'b.dart';\n\nimport 'package:bar/bar.dart'; // LINT\nimport 'package:foo/foo.dart'; // LINT\n```\n\n**BAD:**\n```dart\nimport 'package:bar/bar.dart'; // OK\nimport 'a.dart';\n\nimport 'package:foo/foo.dart'; // LINT\nimport 'b.dart';\n```\n\n**GOOD:**\n```dart\nimport 'package:bar/bar.dart'; // OK\nimport 'package:foo/foo.dart'; // OK\n\nimport 'a.dart';\nimport 'b.dart';\n```\n\n**DO** specify exports in a separate section after all imports.\n\n**BAD:**\n```dart\nimport 'src/error.dart';\nexport 'src/error.dart'; // LINT\nimport 'src/string_source.dart';\n```\n\n**GOOD:**\n```dart\nimport 'src/error.dart';\nimport 'src/string_source.dart';\n\nexport 'src/error.dart'; // OK\n```\n\n**DO** sort sections alphabetically.\n\n**BAD:**\n```dart\nimport 'package:foo/bar.dart'; // OK\nimport 'package:bar/bar.dart'; // LINT\n\nimport 'a/b.dart'; // OK\nimport 'a.dart'; // LINT\n```\n\n**GOOD:**\n```dart\nimport 'package:bar/bar.dart'; // OK\nimport 'package:foo/bar.dart'; // OK\n\nimport 'a.dart'; // OK\nimport 'a/b.dart'; // OK\n```\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.30" }, @@ -1243,6 +1243,18 @@ "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.1" }, + { + "name": "enable_null_safety", + "description": "Do use sound null safety.", + "group": "style", + "maturity": "stable", + "incompatible": [], + "sets": [], + "fixStatus": "unregistered", + "details": "**DO** use sound null safety, by not specifying a dart version lower than `2.12`.\n\n**BAD:**\n```dart\n// @dart=2.8\na() {\n}\n```\n\n**GOOD:**\n```dart\nb() {\n}\n", + "sinceDartSdk": "Unreleased", + "sinceLinter": "Unreleased" + }, { "name": "eol_at_end_of_file", "description": "Put a single newline at end of file.", @@ -1320,7 +1332,7 @@ "maturity": "experimental", "incompatible": [], "sets": [], - "fixStatus": "unregistered", + "fixStatus": "hasFix", "details": "**DO**\nExplicitly tear off `.call` methods from objects when assigning to a Function\ntype. There is less magic with an explicit tear off. Future language versions\nmay remove the implicit call tear off.\n\n**BAD:**\n```dart\nclass Callable {\n void call() {}\n}\nvoid callIt(void Function() f) {\n f();\n}\n\ncallIt(Callable());\n```\n\n**GOOD:**\n```dart\nclass Callable {\n void call() {}\n}\nvoid callIt(void Function() f) {\n f();\n}\n\ncallIt(Callable().call);\n```\n\n", "sinceDartSdk": "Unreleased", "sinceLinter": "1.29.0" @@ -1349,6 +1361,18 @@ "sinceDartSdk": "2.8.1", "sinceLinter": "0.1.113" }, + { + "name": "library_annotations", + "description": "Attach library annotations to library directives.", + "group": "style", + "maturity": "stable", + "incompatible": [], + "sets": [], + "fixStatus": "unregistered", + "details": "Attach library annotations to library directives, rather than\nsome other library-level element.\n\n**BAD:**\n```dart\nimport 'package:test/test.dart';\n\n@TestOn('browser')\nvoid main() {}\n```\n\n**GOOD:**\n```dart\n@TestOn('browser')\nlibrary;\nimport 'package:test/test.dart';\n\nvoid main() {}\n```\n\n**NOTE:** An unnamed library, like `library;` above, is only supported in Dart\n2.19 and later. Code which might run in earlier versions of Dart will need to\nprovide a name in the `library` directive.\n", + "sinceDartSdk": "Unreleased", + "sinceLinter": "Unreleased" + }, { "name": "library_names", "description": "Name libraries using `lowercase_with_underscores`.", @@ -1686,7 +1710,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "**DO** use collection literals when possible.\n\n**BAD:**\n```dart\nvar points = List();\nvar addresses = Map();\nvar uniqueNames = Set();\nvar ids = LinkedHashSet();\nvar coordinates = LinkedHashMap();\n```\n\n**GOOD:**\n```dart\nvar points = [];\nvar addresses = {};\nvar uniqueNames = {};\nvar ids = {};\nvar coordinates = {};\n```\n\n**EXCEPTIONS:**\n\nThere are cases with `LinkedHashSet` or `LinkedHashMap` where a literal constructor\nwill trigger a type error so those will be excluded from the lint.\n\n```dart\nvoid main() {\n LinkedHashSet linkedHashSet = LinkedHashSet.from([1, 2, 3]); // OK\n LinkedHashMap linkedHashMap = LinkedHashMap(); // OK\n \n printSet(LinkedHashSet()); // LINT\n printHashSet(LinkedHashSet()); // OK\n\n printMap(LinkedHashMap()); // LINT\n printHashMap(LinkedHashMap()); // OK\n}\n\nvoid printSet(Set ids) => print('$ids!');\nvoid printHashSet(LinkedHashSet ids) => printSet(ids);\nvoid printMap(Map map) => print('$map!');\nvoid printHashMap(LinkedHashMap map) => printMap(map);\n```\n", + "details": "**DO** use collection literals when possible.\n\n**BAD:**\n```dart\nvar points = List();\nvar addresses = Map();\nvar uniqueNames = Set();\nvar ids = LinkedHashSet();\nvar coordinates = LinkedHashMap();\n```\n\n**GOOD:**\n```dart\nvar points = [];\nvar addresses = {};\nvar uniqueNames = {};\nvar ids = {};\nvar coordinates = {};\n```\n\n**EXCEPTIONS:**\n\nThere are cases with `LinkedHashSet` or `LinkedHashMap` where a literal constructor\nwill trigger a type error so those will be excluded from the lint.\n\n```dart\nvoid main() {\n LinkedHashSet linkedHashSet = LinkedHashSet.from([1, 2, 3]); // OK\n LinkedHashMap linkedHashMap = LinkedHashMap(); // OK\n \n printSet(LinkedHashSet()); // LINT\n printHashSet(LinkedHashSet()); // OK\n\n printMap(LinkedHashMap()); // LINT\n printHashMap(LinkedHashMap()); // OK\n}\n\nvoid printSet(Set ids) => print('$ids!');\nvoid printHashSet(LinkedHashSet ids) => printSet(ids);\nvoid printMap(Map map) => print('$map!');\nvoid printHashMap(LinkedHashMap map) => printMap(map);\n```\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.30" }, @@ -2340,7 +2364,7 @@ "incompatible": [], "sets": [], "fixStatus": "hasFix", - "details": "From [effective dart](https://dart.dev/guides/language/effective-dart/design#prefer-type-annotating-public-fields-and-top-level-variables-if-the-type-isnt-obvious):\n\n**PREFER** type annotating public APIs.\n\nType annotations are important documentation for how a library should be used.\nAnnotating the parameter and return types of public methods and functions helps\nusers understand what the API expects and what it provides.\n\nNote that if a public API accepts a range of values that Dart's type system\ncannot express, then it is acceptable to leave that untyped. In that case, the\nimplicit `dynamic` is the correct type for the API.\n\nFor code internal to a library (either private, or things like nested functions)\nannotate where you feel it helps, but don't feel that you *must* provide them.\n\n**BAD:**\n```dart\ninstall(id, destination) {\n // ...\n}\n```\n\nHere, it's unclear what `id` is. A string? And what is `destination`? A string\nor a `File` object? Is this method synchronous or asynchronous?\n\n**GOOD:**\n```dart\nFuture install(PackageId id, String destination) {\n // ...\n}\n```\n\nWith types, all of this is clarified.\n\n", + "details": "From [Effective Dart](https://dart.dev/guides/language/effective-dart/design#prefer-type-annotating-public-fields-and-top-level-variables-if-the-type-isnt-obvious):\n\n**PREFER** type annotating public APIs.\n\nType annotations are important documentation for how a library should be used.\nAnnotating the parameter and return types of public methods and functions helps\nusers understand what the API expects and what it provides.\n\nNote that if a public API accepts a range of values that Dart's type system\ncannot express, then it is acceptable to leave that untyped. In that case, the\nimplicit `dynamic` is the correct type for the API.\n\nFor code internal to a library (either private, or things like nested functions)\nannotate where you feel it helps, but don't feel that you *must* provide them.\n\n**BAD:**\n```dart\ninstall(id, destination) {\n // ...\n}\n```\n\nHere, it's unclear what `id` is. A string? And what is `destination`? A string\nor a `File` object? Is this method synchronous or asynchronous?\n\n**GOOD:**\n```dart\nFuture install(PackageId id, String destination) {\n // ...\n}\n```\n\nWith types, all of this is clarified.\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.5" }, @@ -2492,7 +2516,7 @@ "maturity": "stable", "incompatible": [], "sets": [], - "fixStatus": "unregistered", + "fixStatus": "needsEvaluation", "details": "**DO** use library directives if you want to document a library and/or annotate \na library.\n\n**GOOD:**\n```dart\n/// This library does important things\nlibrary;\n```\n\n```dart\n@TestOn('js')\nlibrary;\n```\n\n**BAD:**\n```dart\nlibrary;\n```\n\nNOTE: Due to limitations with this lint, libraries with parts will not be\nflagged for unnecessary library directives.\n", "sinceDartSdk": "Unreleased", "sinceLinter": "1.29.0" @@ -2763,7 +2787,7 @@ "incompatible": [], "sets": [], "fixStatus": "needsEvaluation", - "details": "From [effective dart](https://dart.dev/guides/language/effective-dart/usage#prefer-using--to-convert-null-to-a-boolean-value):\n\nUse if-null operators to convert nulls to bools.\n\n**BAD:**\n```dart\nif (nullableBool == true) {\n}\nif (nullableBool != false) {\n}\n```\n\n**GOOD:**\n```dart\nif (nullableBool ?? false) {\n}\nif (nullableBool ?? true) {\n}\n```\n\n", + "details": "From [Effective Dart](https://dart.dev/guides/language/effective-dart/usage#prefer-using--to-convert-null-to-a-boolean-value):\n\nUse if-null operators to convert nulls to bools.\n\n**BAD:**\n```dart\nif (nullableBool == true) {\n}\nif (nullableBool != false) {\n}\n```\n\n**GOOD:**\n```dart\nif (nullableBool ?? false) {\n}\nif (nullableBool ?? true) {\n}\n```\n\n", "sinceDartSdk": "2.13.0", "sinceLinter": "1.0.0" }, @@ -2862,7 +2886,7 @@ "incompatible": [], "sets": [], "fixStatus": "needsFix", - "details": "From [effective dart](https://dart.dev/guides/language/effective-dart/usage#do-use-strings-in-part-of-directives):\n\n**DO** use strings in `part of` directives.\n\n**BAD:**\n\n```dart\npart of my_library;\n```\n\n**GOOD:**\n\n```dart\npart of '../../my_library.dart';\n```\n\n", + "details": "From [Effective Dart](https://dart.dev/guides/language/effective-dart/usage#do-use-strings-in-part-of-directives):\n\n**DO** use strings in `part of` directives.\n\n**BAD:**\n\n```dart\npart of my_library;\n```\n\n**GOOD:**\n\n```dart\npart of '../../my_library.dart';\n```\n\n", "sinceDartSdk": "Unreleased", "sinceLinter": "1.27.0" }, From 6b9d34e9982f8c460718acacd63964cd9a495c75 Mon Sep 17 00:00:00 2001 From: Parker Lougheed Date: Thu, 10 Nov 2022 15:08:21 -0600 Subject: [PATCH 07/32] Update to new Dart Apprentice books (#4360) Closes #4359 **Staged:** https://dart-dev--pr4360-misc-new-dart-appren-t724ixof.web.app/resources/books --- src/_data/books-dart-null-safe.yml | 18 ++++++++++++------ .../dart-apprentice-beyond-the-basics.png | Bin 0 -> 84126 bytes .../cover/dart-apprentice-fundamentals.png | Bin 0 -> 57285 bytes src/assets/img/cover/dart-apprentice.png | Bin 71633 -> 0 bytes 4 files changed, 12 insertions(+), 6 deletions(-) create mode 100644 src/assets/img/cover/dart-apprentice-beyond-the-basics.png create mode 100644 src/assets/img/cover/dart-apprentice-fundamentals.png delete mode 100644 src/assets/img/cover/dart-apprentice.png diff --git a/src/_data/books-dart-null-safe.yml b/src/_data/books-dart-null-safe.yml index 6315d9221..418101dab 100644 --- a/src/_data/books-dart-null-safe.yml +++ b/src/_data/books-dart-null-safe.yml @@ -1,11 +1,17 @@ -- title: 'Dart Apprentice' +- title: 'Dart Apprentice: Fundamentals' authors: - Jonathan Sande - - Matt Galloway - publisher: raywenderlich - cover: dart-apprentice.png - link: "https://www.raywenderlich.com/books/dart-apprentice" - desc: "Dart Apprentice will teach you all the basic concepts you need to master this language. Follow along the easily and thoroughly explained concepts and you will be building Dart applications in a breeze." + publisher: Kodeco + cover: dart-apprentice-fundamentals.png + link: "https://www.kodeco.com/books/dart-apprentice-fundamentals" + desc: "Dart Apprentice: Fundamentals is the first of a two-book series that will teach you all the basic concepts you need to master this powerful and versatile language." +- title: 'Dart Apprentice: Beyond the Basics' + authors: + - Jonathan Sande + publisher: Kodeco + cover: dart-apprentice-beyond-the-basics.png + link: "https://www.kodeco.com/books/dart-apprentice-beyond-the-basics" + desc: "Dart Apprentice: Beyond the Basics is the second of a two-book series that will teach you all the important concepts you need to master this powerful and versatile language." - title: "Data Structures & Algorithms in Dart" authors: - Jonathan Sande diff --git a/src/assets/img/cover/dart-apprentice-beyond-the-basics.png b/src/assets/img/cover/dart-apprentice-beyond-the-basics.png new file mode 100644 index 0000000000000000000000000000000000000000..c9b1b44b3b26dffbdbca3fccba51ebfbda33e817 GIT binary patch literal 84126 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'dSpy4TR~Y`^IQ$*tCE62)@NyN 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≪#BwKe)kTQAC0UIHtAdn$HC&9?WCJyc+rIcLXv*46)c0n7L4)%%z zpCA-SS7B=bEr;v1PgYWjkQNp`$dD4}Npc+>AOV6Ef?#Dd1t&gWCeaY!s-w;q=45DH zWQs9nSnQ)_OqQj|Slu5P&SKlJ+E&Udv{8(U%_Cj&*z1v~*hvw}NzZh_>r_pAy}UG) ziDyyff!rZmP0k)QJX5x+)(hux!fDk-)vOQS{mTcD1E)znGk*IAKbgR-6U2xy@4T&( zQcjfu(IKiBecfA^1ObSYB17VW6XUT6o_tE8l7VpoVq~NvXAB{_8pGL4+B!i90=Cb| zIV&q;SBR-bih#7OQV7z43kEKPjuA0RXq^bs#;CGvi-(N$y)Y`!x?@I1GBt6|Sf({; z!(%*lFbWrkIeBWAWYfN!P%DLK)}DvX8_tibq8>Efs52IEIRq11zCF^uI9!&8xfbhI z#?D{ZnVn>kOcB%Z(WDk`6-hF@;n$BC!)a2_P#FD*FY^&0NG<@1uJt~}mT4)o+@%Q4 zD6uxFYT!5n^N9i8h3L2x+W8b?R09f(hnOTwoN*n&2%J`Ye93PuV-i7fVRqKXvKaF2 zMlXf;9ZZDeXc3TjU=SK6IxgTKwI$e27{q*QxVBp7p{!cR=55cU7U*u~R}GZP`exPG zC)R%DmC7?l-7#cfb>z`ea~MsAtRnD<^P9N}k7R6zqLfDUOc{E-u%opbl_MW*FqLnz zv+QIe3L#ORU+l_*#%YzW-*nXq;54aci1g=wdm!&)ic!cAJh>=9!8@TOc}O3W$y8-Z z&P5-Ei!LmRinkF_X`K)vJTy}>gxCv3vGLJ`z=`o>4PQ)ELz(1=9dBzI>XM#Rq=*=^ zFi}RO5Tr~YNdYBU6mSF+0cm2CF%D!a6wgJ<9jA5{8!_dH1<&P>v+Q{0;4qeqY;0he zk*N!J(DK)xT=4cT_G$DD=S%p!y%74*o>*YlR-xJonv|54sY)*XC!4~ zawh#c3H9JxkBQ+lsb}u_|02Z{i6STE8ZS5(GPw|%<6aw*t_Nj;1%|HUmWW5Tq;d!w z9axzUJD-?@M-ie-u{y7OYI@FDE<^H>kFT}U!yt2+l1zwlm}R&`%<9-BDHV${!mEJ5 zxnYnbO*9#djDm!Qw9?he0E#86a+&pgAM8$KGNq8^4E145sxXQxt=zc27PZoO?|g41 zNhx95qVH1?`y{z8Qr^~TxUo!{jabxy(Q?}&ll}fE>({GTCK;#0x6=+Qv}fG##e(^_ zyl2UQ)1;m;zx&TODY+0sV!T~Gwy;APAekq->U&u+*LlWlchdGDco)eN6GZz<7h|O4 zyO0v&!~%sxiK{_MJaJEAW3URT%{GqR9k%C+3568ppvb#&-3&Q#QF4MH1<6$h84zS< z60?XZ$Y{9qG8!;2mGzubrrSZ`DFsSdu6T+LS)HwCp-+OE)@uefm&r-Zv_fxWm{rp* zqVtjKuJ7}lnIT^t$5OA1)D;+UD!bhBO_s}Aan(4IuCr&`YlwQ#uTAS8u;CXT>jh4e zdgiG3`q%p8BE^_ksvmiT?N#tSWxS1y5^SL%g6l&c1hb4Gg0aYXXj?BmC2Io)dC$EJ zed?|D6nRF;bIb4CI9_(yMm4`UJ`@>mrDa@ad@va->p+$xMkQoMERqfZGC)NJNGW?L z0|Xs3qLtER!_=U3ZGSFkVO<;coMko=8x@DgGR@}8I&@J9Hk3N_Yroh`M1m_anzyUG zEYS6eN;{nhzTl%>xo?cftsfa~Pxja6501}cNzARh=PAgui-S&Pq_(WxfER=yCyl70%wVFG%==-z?l#XDeT;~YFJ8r ziXA9p!h6RkMLHMvli3_ypX}~4EIOXCv6j`;6#d%goUV7A5%|+bvj_B<1Y(fT!mu6^ z99|-pF~KO+l*VW#2Mq8wl!Fv)2918sy5)-ZD`JPpnX_SG`a^ij0_B0Z2)r2ZZ;*^$~(%T(PsEi#zOz zYlUbWL?tCR!*OYrB-*|)Q-LHxcq-i(B!HL&DG;MZl+aPfXdn|(!~{t&O-8JSa4J`& z)F+9DL9u2&arEuR?Pb@5HXvp!od~W6u3MUtIX957V^JS7;Wx@KZ~2C7ZIx^9nQ~=( zkd4@Wy8$1IE*-Qg>+R^C8$8Q=oPXz|iQzP|k4b&_=r#i4G3vG(= z6q>!)PS>5$!nMSN43txW90AB7A+#8%#DJ(Fm=+>xcsb(2Ix#%j%ouaU=Ddt)9<(n; z^>XDXaT{7KLUO(rG5SiRloWB>@a!ZCn|sbemSZzd-F$XlbUGgh(Iq|+;pAa9TtBgO zBr`KG-Y72Xc&~c&#^z-9EsrIJ)1;ma%D>^W`XnR4CrY;Oi8|_nHYs>HP@!Hd+GXQH zn6^^;o2c)D0*NsvN&_WjqP(>6255b*)D10H>i{58u zFznZy`CM*4F{;#eyel%CCiSd@d;T$z6ch=*lVKgBlQH#NN+?rQ>vlB{6rm`RM(1oQ zxX>|xMRJJ}QDO{tp6?R@*Y z-Vzybn$)vF`Cobkl=P0st_fHNpH%OnR=N~Eb<5rbFC^Enmc=fH#3{N?Fs_IIpJE~+ z$x#KJg^9p#s5lI zAk#;iBhH50~NCovbyI9T**g62XgSeVJ&IzYf{MZpdvTvsTO6loyW z{?b5B1kOBogspkC)W)_|HJz9?!|H)IuN9thI!ZlrVf*`sAW$D<>tpO%>pf8nh*G7t z53Y?og-AR(I7xy5j5t{)K|I7rTyfth0s~`8a-MjAp%gg@#<|v#YtB^HcSfZ#FU)9M zWyAyb^P}KHDK+=0cDtqDG$f)jqm7Xn5B7#NGh;riNGXX~!p6qDZ50oy||qjcu8N(p`>0#`h-= z?iVGy6rMM$>vdph<_ik{?3%<=PLp~T_@{qOVvONB8E#u&w~@I-o)bxm!3K&%NKq=k z>InKZmg^WEl55R;`S<&<8y>IGrI7p*WX7bcI5Y1+i z#imn^xq*zM-Lae~l}E!(rgZeJ(Oiy3xgKjDtm2~3l&T_qNK4YGjmB#H7+f)Pbc!vECCyjP+z= zxH&1ugG#WR1@gj7Oi_>)q$-w(D;gIj|lB(+b&HLI&rOU1>%yip9H)nHwkOjjTvqE_?tv9{Z!ty=^A&0jEhlbNrQmG%-Tr zoPj{S3_U`d3l|een7d*e%Df8g9W%RxuU0*(|s($}%R~bIwG^uBf%-6q|F#-_-SfajZ zI0NStWFn=!OT;;YXEmcPNRhHC_3$1sDK8Q{m~h^wNC`yJa|%+0#6UND^CS)BTkyhX zc~)gS&$2{ZFc24IN4a23EXqo+BwOlWRpaODruL5?9nTu)nB-EkAxm6pwH~AxB}J(s zk=EoXkn5w?38r9RA=<0Z{p^PK;9{InEM73C;GCyLp9&uw2JmNCk_I~_LKdnge^6+) zCZp2HWip3X!c01nHPuY79)GtzP3pHHY<;ID#z91!gQd_~6H|msoRi=L3V=;6Dwk3q zlga3aA;sVWMIWLhQYIxL&xl7N3JFmrAaOm0EJL%4->;G-UH(5u%WTQs&%*^)SzPQ&Jx*<5n>GByijWeqU4+jU_|6PO=8K& z^B5xIBjGrg#1lY@y~!hmGdS zD6E-mH4m=Jq!equ>BOGyeJHFbr;;ndQpdJ-kG)>)b3~`22wXh&Xk_?sr@K0zne2ru z@f08c0_Q^JIk%bs774xsf($~`6<{gB-hRa8>Im1 zFF?e6(P^iJLS>*6Y|0C;Eb0goPY$ZAO1%V@eVGq+l*1W!aCYsA!ECYbFN~G05nz>(qlw2ocF~B>@m4XG}F!MhTGw zz&QhXHbsb@PljU9bqirhne80Z=L2}1L-0H&v?Z&wFj^zyUJkcXr~EO?b*Z>Q2$aCV zZ3~1_KT$6ZX3b$aDxsd($lZPzpDn$E6+;{hDHsi(F)0D>mz!$bEy`q59*k9^b>MNl zR_~tNzj5Myv)RP=oCtiF)1;oMn7=Ub#A9TFd(xa2G1W2CmgVcf01b#J1vD_2ipbPD zL2D<7XB5z8AOd$$5EDQMxv)WI!9fZpSRi5)UCg{xMpYWpD+4YV5V=5#bqgQ06B>wR zY_A4o3fT-%O7SISz1b@28!> zM>ySIio>FXcDg4@aW!PYH=eaYtmE(JM_wHPL?$5rS7(U$TDD@1nQpWX= zgWG<<1;9lHfdne7Bqky;786&(=_rG!Lnll~FtN@e1Y=f8 z$bbOGloEM4Q9u&@xDbe(ClJBb0|2>>iwck`!=>ASN^)IiI+Hsk+AOA0_o1qMVqsmK$a5_poL+M3d;)G=AB8!rf0EjV`V0esz zw1zR@g69M-LO;g@Aa^=^})*90wuA?>a6ZXwCs%LoAI#Y6lENq>+;9& zyqz+az|xUxC`1!NeQDbVbUE<8p5r5(CiM(4ju==35TR|T2apsQ7X@0CsdZ1BE5)6H z$aBO##)MpPo-|?vMrFfMhBgRL5^x?-z}j32p*aCen#zd5&y984>%lM&HE8gAgsBs*T` zmT@6rO(?R-LWgCKO!+8?x&npbUMNK5!%AycXn4&45Cjlo<83;7TOOV$fEZF-hd{RN zJS_7T0tdTd6)QzR*%?U;HV)=jeYL%*t7@dC0|W>b;BFir`e5#784;oDqoWh6xG}|r z;ZYRSGm}s>(Miya3tH&HTa$9-R8jd$m(1>D4x}V$?J?i9Ck$BIDl>0hbNnW!Nj*ah z!o)7liV|6*$X#-pCr(_j5da&ILWe^DE zkPVyUGnw^Ql@WDwMT`xf<|`%@nuFffgq&r`M@KAIC)ud(y5lG|%VKlzRGV&+2fc2I z<5G8V!*BYgljwAss{VN9W@SKWQBkmAbp^I5n-YzY@35yy{dOfheiyiBE^`8u!?gtf zFaX?`Cu$TzP;a zM}!LuhUFpll(-rLL2}!~5fsaet{AVh5gZ&K;)#RQ=R})Ay~>XBS{AC4q!bWCoxr68 zG`P%-Q+rA$S<%uzpxy+36 zO5lS$4CBoA77RlcR`0xP=1QHEZH zPI!+X7sd7{mfM`_8*S;7?-(uSY%{EE%%YRj*|j%vueh|jc6KXLvla^%&tJ*K6U}N{ z!XwYLsb;Qk5FimS=yg?yexU6eJ;QHyn$$DI(YIMrGWzILmK+ALFTfKJqG2%t0zyQR zfJ0Iu0w&1_!x#nKGk_66feRHoBIYp=h>=)U09=6qo(m2DLI?o9VNEOmrTS~L+i#C; z;HuYEc7o7$1m^s~meLCl<)neqJJisuB_?$4ctI{Hgid1t%cCggIrrIxjTJh5VuNk3 z8zhgdEJ}v9!MNNVb<5>Q@9i(vEFC=e!XqlJ&C#%I=61R_)|%~+OoYhXDx6r(8J9$HtOuo`z|wj)+pkkQ7;TRSea(DJu@g=zHd0`VMloI$ zScINU59Unws;Zl;jWN_Cd00Q$Ca*NPq>e&!In@VYmDIZB zK{?xZt69HnYImhw+qm?R1Oxf5i&d2ygvdh7Jh^Nr#Y&jSn9AZhm;qYGsoUCV4#()b zdbvI;>1clA;F7&EOSNQ7R;89z9IxK{7(R;A72h+HfRuQMB1G;qg7j@JEf?TGMB;&I z03s3t5CtGKGyq5eV74V7+??$qM0j{`NMC?Mk%0grS|bnZm{xAqe5m};1=Ew1-NIULGlif9D-=YGDKiy0%9&%CPriF z**$Z2;sB6#IN-Noxm<=AyC_D>*lZVQ_$QgaN?55z+*5RE6xQ3154DeYK?rX2J)(733{O#gsn~;XW^jp1+UHxN86LZ z&UnbQV4_(cgHjSHlVLep3MsNe=S&%G#QRaHgwdK&q}VJ^0&i;416lWpNW18&QNw() zOHbfKJ+mTXOQ(^Fos%?7F@&aFwA$o0nk>l7**21pQ3>%&3y$CHG^uAQsZTn?CEx;Q z$s>tmBo~YX2heIJyd|H5A$UM?q)6ZdP6Ss#@Ca~eAOz=%Yp|%K5+sBKNddSZ1(Xzm zh$jdwWnwzk3y-GhJP)Kh;d$YL5@B_+oF`rGZ0PO08kvn^7?WM6tZmB3D_-WxNFjqK zC`oyq7mQU2S)!D9V$>0?E^3_JT=qmkGK};kbW$YWr&O1DFMZ~Fg5Q|(8>y04S`}8^ zf;U0M7;{=js;O&Y)b;B-j*sGW#rKRbzA*rSDI39)OWRj`(0 zH8!?C;e|W8?QB^r77^Xzpk)Cg4=$vDGQLF?Qji>k1fb8nhv3N=a#$b7WoD-17dKb0 z#GWBoxn{sH*yU=NjdQ=fEF$Z0Rqd@GUzcZRT?=3t0im#OfDBiseb!IcJ;O(F0Lwr$ zzdA}iGs(RA3}Z~PXa!?U(1FJgxJCklAjX)I(#Hs6cyd}QqZGKvl~k#b^T> zYa$n1C2;NrL2H&Aw1VI)QPYtYg5q+$xY5)%ENfC)TXOx$az^!{sZZujm)c%9pKL#0 ztf$kRq0MTPt_B1T(zhv#ED6U3nL6$zXNDH_KJ$1b8S2o)9C~Gq9Gm;mVWvC{B}lhM0c!Il;MIfD036mWzq8_NV;rLX{}baV9gPIDedG+Wa{@+fMddBptx1Xv9wYDjTKukupHe`Y#6X0A3E`(9Z zFvd9;XN*a-hJne%dD4PQr45rtMM;&`MoSUgjd#84#$tW=Xw5cr5HYQTTQ8UMg-bSY z%6u0S=S(tX3W}m{Drr2Y#s#Y-WJUbs!E!v^+8MGgZ~~7cT_Rz%kvijSSf-$$G^MDr zG6dPzGRsRnHDy8W@a*$cuLnuiTsRdYC>LzByU`HYwTyCFH8)nnY%+0Fn%?#lJcGe@ zbV*D7=n=>N+i6nI3_-v8wghx6YNOm*7cqsX1qBEen_6?upNdFo$%GUPPd&kv;9M}t zDHz6BN(dz3bgqQp4Bb24^2p;sku-#!NY>T?NT z35jVX5;r2Y4M>I9wbvfl$%q)(`*Fs>SX4Iy1DA|3VggLx3=BkM+rALwLqdv{3$r;L zjL+ZyvbzUS@Wjw{;pn7p`gJ6b6pVBf@FFAL zQT*U(T^IuZ2BdWIOrU99VH@~#ITd-7V( zSCNAR6QnAmjL9VDQZOZzlp0A8XN-|+!;J&Se2RjDIxyFO_0C(NAi)^pT#)pRGbO+R zA&SHj#W67=)eR;Bs$dZ;NX0obylrC=!bL4piVz^{E%htgkYH`2Bqv%N9;*qKP2hQO znk7Mu<*IY0SaqUEl{}U_FtD7pEttxL6q5VcDgLgW0PUn>WlF(pS9 zv~oflo;+zm3B2KOt`2!xEMy$8(9||x*Ymxdt!upZRdN~#$CcGu!<&<#H1)QsE2J)p z3F3*1YG^?oJthes&1q84RHFA@WS}0f3LZ%2yhFWIsn!FG%-FQM3`(UwpQ97sUo5MoE9Lx1XbC_w1_UYKw$OuG znR%>&j0Drkyz0VWE;}(DEf(5#M{KmgLRCn)NW97gpA$7ALXK_Gic3coGU|KRnrQ&D zbopd?;RTn8xH&P#<|9{6M@xr+jToOy&Oh2o?qdjpJ)8(gX&Y^TJbH$Y>U72TjBxRi zom@mpNFg%7x+sGK^FC_M6F~sMCkh0iLvTs7uI}5;24=0CY>ictN)@IW8qG;D&KYBz z1p+f%-MlZbvQ6zA58jd_#uJmmK{GBTv9QXy7SXVnT;jw-Pn zNa+M)T5qjSUKw*{icEoWj;hL`Mqr!)KmunX0#PskAm60A?|L9=+vPq;=A8f&OlYSz zyb}TvWMtiBl}DjO8W0zVk%zwD#1Mfi$NMF#_O>p~PN*sdU0v#OIkz`7u?*;!F{db` zX0vl=Hjl3f+d})gGP*f1yW36UwU_8rh7}*OrBg0qvfdfatx;vvsgXvZ_u~za$%k{C zj#9tFE4^>tz{#y)Y$IY@SqV&_;WQcJF!jH2)Qx(QA>hUlW{Pvme@(L6Ir^PpYs>P^F353Wf> z^jW2P#FWmAXGOMx5`-u{dL9B5TblCm_~>on^fSKSfuvqINfZeHAz6gT8)8a1+i@vs zpCa#@ZY?Q=&PCg_zOEhdL|nQ!U;(+@+!|(5F?vcOfQY~#7$=4p+t4=7MZ^@*D;~UL zfssxmNHgvw4AVQ-kTgV$F-lTWV4V9rk%A`26KO(#&&IhZ1_NK)hViZz+iGt4n6pI5 zc}`67z6%kaCPTe)FNk_#gT_Z*C2wQhGUr1Zy%!-$6PI&JLNXFD3LIwT z-rgh^xQVm(yFv0g*EOtlX$MtedY1~1Y{V@9l_j8qm`TahtIiqHdaVwlf6@Vsb3PF5IJ zEu7*?7|Dd%2;66bvRiMdC)$DqCO5lCNf)CKi}6-<_0~>`E5Qi=110s+b7Vu3JRuK0 zK~R@uur~T;(J|{*5i8O$BDi)15`?@I0>VhC&6x|kqgfg?M`GNA~K!?V}kLVlvLtooGe+(t%#0+KmOKz zb!Ix1tLUt4Sg}>HajwBKCR}2%7rblw(D8iAtra2zORQt1gNsQaNizA!JJ;%x7JSE9 zr832aSa6jOM6ZkKP<$dKl|o9K;R7h7lmvcD{^DQ#oc=QXj~%7X%QcHpaZ90H2_P`y zvGab_Ccpy2N48b= zQf{3o;`@{OM0v+YgAvk+V|WVbT>(2!_^r_J%fzK$#{WPG16!4zRv~X&^vr31LIB_* z*3OWksL3&wPNaw-#@zN4p*hpVbhG4$V1j`F4j?f|MDk=qt;XorBtz;O=R~wAcrd{- zJl&pSf(t+b5)Lw;mFP32pbHB*YBSGSP{WLXhp?l|Qpz=5cdtYw_Nz!-lG? zrYta_RY2-6@~y}b8fBEvZ`+5|LOb1D-&~Dsn^xIS=dP(}xvtfwO!Z)*c+o3N&(By` z7qQyR6F$0+%cT6h{|b+N*`dNy{2f15;oV<#BJo>^Uf_Qyj*z^vC#AIkQLqTc073*8 zfgu>f5W5J77)9i8(o;+r=RTiqWE=?s42c7tF;0QV-`EU6$^os_y5VBkE>|KZ?xbWQ zM$RG#EP|{ZkXB$61yhKF7BWPNSp<-fAs`0m6d+=kv_fnM$ydYQ`_l&xPp?fcOgHzI zOS$qbRtY@m0JUaiHV7wLW{aUgmz{N&H+2AwK-1Oc0X5R-EX}g|e zFQU+icn?6gQ8JK^5W&-2B~Ann<^b|Q^ePX0%`EPxfMR41bVYSm-TLZ4r%sL0l zEHy@sd}OuIBomwJN6&XnC^tL3(QX}~Sq&1(9(N3`96ot}9#>o2m#t84Rg}SuWzMt= z*#_aG`M6B#!vs(SllX67_#cg9-2<74JU5f&BF0sr3hBX-g48ZVYS0G_Sds>*8a(ly%fmk|;<$5e^?E2Iv1=U3va-n>5kQ7>pfRINBSTAD-3Q$0% zAiA6Zh>m=p!zv#jRbt79;GrX%>QQ$R^H)6g;Ogqy!TCK|nANZi+u3rl>|wwPr&F*d zJW=W6+`z2I7jy^#-q6k^e*2A8voNGhbfXwHl)ANNU# zlJQSlU&Gri0{{w4A$czGL4hQP0|CGJDar6bAt??|Pe1b;%Lz>48B199GC(UBnX0r7 zaA-wvK|)H!qDKL=!U;sdaZ`fMCdFW&i3kEjEP)V_+GzNKdK7(ZfqvvtT}vSa3w%XF zz}qCfhyVhILy$2uEhq{mgU@0_#tA8C!Qhl?qYM!gdm!toW<26V4gxn(9G$&m%RTbM z3?D>%dgiW)yL{=ml^=R$_x&^NKXKSdJS9A}ocW{sD=+cPttw%a&b$RPoed1sS_(3g z979?YAcn+E1b_h;3{OR#4-JUGz!VZoQ6y(w=p!T03AqSx2S76zOEw9>dWEQ1BvwF2 z@Q@+}h!}Yk0V%KyOe%DgV1$EjrEo#ke!^2ggkXr&?2l`1nz$h+FF*HWTL(NbqPsG8 z(iGbxpI7(xi*Z%gSdQ|mo2rwo31!G{f0tCzbwyrp<37F`>IF|{D&?wuqzU9Xajici zEy$E(Fk=Vc_$WTklM=VT)XM*IWyzTUNZ#`euNw%&{=sj5^I8HRanCouCKHGc{_ip3 zDPi#Pzx><`i1UB)!#6(A&ny1&eVIU9|LY&Plo&wb?mzw|6M^X8^LJmrl6b}>kAX@a z7663qJ!Js1mWh~hwYjz`W?kak5XKuyWI_-q%SDP1oB;_b`e@fJ`aTF2U>!g}&qjGf zh^F_ouIKLH3k~W{?n&z_`}QahWm-lMDgqjDzRHJz*@<2YuwkEWyJjeGR#ux5>|2laE;Q6dL06_Vd{l(D#=O4RLyzpx--uDl_@~R^91%EyG z|MX+m9QpV813osCf zIm1eoVv15|&{{Z~*BLZKG*R@VSaN_+ybsZ!XE&crIsyhZ66E-xENd?;_`N4b17LOH zbiV2x`Wvg^_94vT?5DhWRb|bbl`AeVwxA0BB@HT0F&wXM2 zhu_`O1HbZBe-1Z=d;UV`{?zLm&))hU|JLWc=!^evA1?g$5dOkXts;BJ&wbzX?t9HY zcN^a}z<>GXLrV|5{wKd1f9ek9(V z?iDT=vo#eFj0=F6Z&rop9QfTdA=kgu`&eDhZ+o$Rcrk zOdoe2$ixd@p4LAS{?b>x>^a~0^RttV0|5KvuMZFZFITw`ta(g)s+6zq$KSro|LiXZ zA=vuim*0k8eN!@D{c8SK{(TL`;_U5TFu3=}7UmCrKL4Q~SV|$%@q7NT+WhhM<=-40 z{<_Ot2-aO{e~;MuS;z1Ukh*6a8CdEdj2eP_ic}cSGC8g$n?$TUb8%F4onS!@@=4*C z-rC7x6oLVX`DN{+2+@?nMmS1=l0fe%2HW>*tPYb(2uR?76pm>F>cMHOwOPqMM>a_!BS;4bG#W`zG{d9()XE=I;RRHwtAG{Jkn0_ASZ_0AqwECql+q>gR@pnzp(QHnw5ua`xk3a|2Vi>; zq8e>yF)~36M5%7)p#!M)!4W*blDDBJ5TiCImNIS)&ncMLMZ-#fb&hN+gftMDM+X-L zAbY2Q4ix0gLIG&$9CS8{y=NRUM1bXtuz*zrlX}7cpnNjCGRu!ui|LN+FgsZH?a9d8 zxZPZ-OO>!vMPb(0+k3*IAU_(^^9e1m)%zIw3Z_EvEt5sn3yUmdGSAL_qOJI-5fD2f zAW8r+dvOTwaT+)AllQ%HYkX-sz?)YRH^oQSV}M3yeg2PnJZ;BkcfFy!Jscl0+{D^9 z0BrQB=-+NNZc_6%f8k*3aXd3xa~N3Vi$NJhl;SF)1@pRH1Vm9xS&!NEt_e~F5rQfA z3M6m>D8}Z1Vi&=|tyk6oARxv>j1jAVOsbsqT*0_B1Xn&pWUBAULPlgAIT5szydfAX z`=A=isvr>xbj~p#3ZULYPu%GQ#s~$X*9wG7CKn9o)g8lQw0?}{>}G$aI_c)^`OU+u zIJ27fmA3T|G-OAEvy;X3)J`hzH@5xJu@fMRR%N+Xk!-e!AW9Sk;}<{Cb|U!i`q$X_ z>Tm-OKbiniBg|Wdr%3<4SIPk@;K<`CtgpuavJB!rfu}`aPv}Z69m7+Y0)o!a)eQJR zi9p5hOfZbIo&msUYf#mQIzLzUk)$h>(4*lHzTT&L?l@w^XURb>a10Fg(hdEc|-S4MH3zv^3V|qe1VRr+ zCf0@m1JFmIDNiJrfd%n0I4+|ElTteHx>nGMX9J;v&HG?Quo79%4AaW5k-_J_%kRE1 zI~b~_&gv!8lMDxLbkV21o$K8=PkqBpmK|Nc_m2G1$^N$oo|%0f4Fr0CYaP_H`>fjR11K z&UZ4x(>NpPXUHZ`;wiCwF~Uj0Gr>{!Hd5<-0CVsz(z?mJ+#8lv-8DU1=(Z0*@CK!0 z5_!RSgal(0=a){x;))z<5c7bKLNibg47!-Kp9z^M_}BvifUF`25fCAH)msKBfGpUp z;i?7;tT!S$$CNi92=s7HEA-B0a6IIq)Eyz(C?I$n^xNsFWh3OY?kJxh9a6 zqpsDapSD2?MA^fyj(Da)29X@ds{}^9l)*F40ft^7tpbyQ5;%kg0)efWiK3)>fDpKo z)$`{MxwZ#J?R;XkS5GeAS!8~1dN3Pt7H7<4+x~q=w_SM7vdjkalfD~Hd}oEthe=83 zAS5H;(#$D*EFZ5s5gGx+{_^YJ`T~*{2dl3A()7ZgJ>m@HH~-pm`9J>Uh?m@*&)(S! zkU#sk$NX2{glK+`p|>=GF~mE5{2RaIN9RPZ<6FP9<_tl-^8fzy;@{Qnm*V+9dzd)L zPyW(N`M>@dVt6LhJw=RxgS(VC5f4mA&9c-qO$=@8NKyn5yojFioej;B&;(-k(aQq0 z)11Y`D9{>+F8JURLy*J-0(kH~GKNHek4^xTI2R0(sUkoyMjiSV4BmGs_{2qIN&yH_ z1d%8Ph6pA=N_)p_=onEX21vmvAXlk2#1rF*RcA)>+>Ws^FBGqsJH7`oY`oQ*~(xOt?h)D^dv{ngeev-%^e&QS`{2NK}^*i4Bh9|%O%fI}UKVCO? z-amNRyXwf~-k<%0Y5Bk1P`>+p{uNiRdB_WY>lIPFKPh+gh53u0szB)C3{<^?3LF&GNRV<}QV8U@3sh7d` zf~S~L@3|l;Bj+S}R2yga3@4@;G3E~rBNL%x!63vC!H^OV5~toX!2*;JvX7mV#8@9m zBdtkFMlM0fLPJ7wqD0Ik-g_S%ON@||VgTz!1R_{>thGcE%2b_?6p{!b5E&jhfkShl zx_+q?v6S@o9lN_{ig6}{7-TCMS4U?G!D^og&3cql%X)3Q=rujjhi0{JMK&69sf037 zk(KS$V;9WzPrUt7HznA8ODyMX`Ry;f_@bZq#s9j#=S%hi{h7-W;SK-gbMSY*^gqvU zK7*UojX(Rt?9YDQf4rn$^4bX={NYxqN{V2-(5fX zE5E$H=XDnY{`}(t&zK=N4FDV-aLjqdi3u4Xg5?rG?jbQ8-Em={$rcPqVRZ}!2N@7# zu;2v80VIUv(DYIkMh~NQOfVUUg%AwdmRFhPF~uyB>qUqnN*NPZZ~&~b#0a1uNr9&| zz<35YXdpI$oR*9LNwJmOYDQ?8hyzL?Dc%V%luA!-93A&e?U=*WYFZnw# z<`)8koc)FJRrZyyLd5#9=L!IbzxF4-b8_E(0ugxdYi=kYz4@!YcXII?1tRcYzIi4g zuYc9wd8PcE*CGPlpZ|}&#Ir%xFeqr}7^sFq0D;3$n`{(A}oBM4uFUjAfP5_2Xc%Ncou*F zSTIUFGnN_Bob`PGAQ2>FM9``c1`*UVl#JRY+cY9s!F0A8oEfOLys(_FuIS9>`Y4X7 zsy=8YYQmOHw=wD?vZhhdb@MJ8L_5zm1`wf6c9Hr6d~_d&E50-^@A}oZ^&C$j);;;I zAA4tHIQf}}_ew?mwSWA-z1=eaeD(9!?#_g7UjL{6%V##f@NNPNkN-?}UJ2?S{qAqO z3;--%{%O0D30lAJfB&8X2>|o|@}6@gWBt(&|D`we5_rZdKEMJ+Zij(I8)HZmz**pe zq~zp@XN+Z|-R*Iy1qsCfgmoLTfo4+jn2KCQg#_zZM7miZi-^KILIRS~DM*!)BN8bk z>lC|Ln3joCN-iZ@t+U|OWGIw4pTg0=gu?vK~~ zI|IZ2KbXO@!v&*2_#nvSMbAt4Y#(s>;V3^u0d_IJ1nWc$3$ z&Hj3aEz}McB3`EP=_4j0Mq0F&Pi5LWXxQnuArm@k8Aw%(hgD z0KAcp6h5ct%R#H!tTIOF#mHMh|A~ z2a4iAvTzjw69Ct`5S!Cn0KrHOaB}OT)e>;f1fC0w7_0V=hyf0OB>+!F)e8sZSnyav z>ZIT}w5u(j!^BK*iH#GcyUf_$Fl_>i=n2V}jY^6qcyh$ZLLrlN2A$d=1W9Hq9G4*w z0Le�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 literal 0 HcmV?d00001 diff --git a/src/assets/img/cover/dart-apprentice-fundamentals.png b/src/assets/img/cover/dart-apprentice-fundamentals.png new file mode 100644 index 0000000000000000000000000000000000000000..3d288e035030d55c6009ccfb13b139828a0e2bd3 GIT binary patch literal 57285 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�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 N?5rJ8caaxU{|D(!d>Q}% literal 0 HcmV?d00001 diff --git a/src/assets/img/cover/dart-apprentice.png b/src/assets/img/cover/dart-apprentice.png deleted file mode 100644 index 91b8de3e2416740f8ba6dc3b2e36a04d2496f801..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 71633 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
nb@Bm>--hHinhMd+!jRPri-imN)yr9V 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 Date: Fri, 11 Nov 2022 17:14:11 +0100 Subject: [PATCH 08/32] Add dart.dev/go/content-hashes (#4362) Ensuring that the link doesn't go to 404, instead it'll go to the bug that we should write the page. See https://github.com/dart-lang/site-www/issues/4361 Hopefully, this helps us not forget to write the page, and helps users highlight it if we do. It's certainly better than having a 404. --- firebase.json | 1 + 1 file changed, 1 insertion(+) diff --git a/firebase.json b/firebase.json index b788c60f1..9a5cf25f2 100644 --- a/firebase.json +++ b/firebase.json @@ -138,6 +138,7 @@ { "source": "/go/analysis-server-protocol", "destination": "https://htmlpreview.github.io/?https://github.com/dart-lang/sdk/blob/main/pkg/analysis_server/doc/api.html", "type": 301 }, { "source": "/go/cloud", "destination": "/server/google-cloud?utm_source=go-link&utm_medium=referral&utm_campaign=go-cloud", "type": 301 }, + { "source": "/go/content-hashes", "destination": "https://github.com/dart-lang/site-www/issues/4361", "type": 301 }, { "source": "/go/core-lints", "destination": "https://github.com/dart-lang/lints", "type": 301 }, { "source": "/go/dart-fix", "destination": "/tools/dart-fix", "type": 301 }, { "source": "/go/dartdoc-options-file", "destination": "https://github.com/dart-lang/dartdoc#dartdoc_optionsyaml", "type": 301 }, From 837e77f4420501676db38056a708a824978fd763 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Nov 2022 00:31:18 +1000 Subject: [PATCH 09/32] Bump site-shared from `cbd9b39` to `3f55d07` (#4372) Bumps [site-shared](https://github.com/dart-lang/site-shared) from `cbd9b39` to `3f55d07`.
Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site-shared | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site-shared b/site-shared index cbd9b3909..3f55d0770 160000 --- a/site-shared +++ b/site-shared @@ -1 +1 @@ -Subproject commit cbd9b3909699a817cb945a8faeec9b0730cb4fd7 +Subproject commit 3f55d07704b43696ee36ac281a364d4f3faa19d2 From 09ef968e7a1143a7f98dfc081f3805cd051a53ac Mon Sep 17 00:00:00 2001 From: Parker Lougheed Date: Mon, 14 Nov 2022 14:20:33 -0600 Subject: [PATCH 10/32] Remove non-null-safe video playlist (#4365) Many of these videos predate Dart 2 and all predate null safety. It would be nice to include an alternate, but better not to link to an outdated resource in the mean time. --- src/resources/videos.md | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/resources/videos.md b/src/resources/videos.md index 6bcefa21d..b7ee3a18a 100644 --- a/src/resources/videos.md +++ b/src/resources/videos.md @@ -2,7 +2,6 @@ title: Videos description: Learn by watching! Here's a collection of videos about Dart. dart-playlist-id: PLjxrf2q8roU0Net_g1NT5_vOO3s_FR02J -smartherd-playlist-id: PLlxmoA0rQ-LyHW9voBdNo4gEEIh0SjG-q --- Here are some videos about the Dart language and core libraries. @@ -14,7 +13,6 @@ If you'd like other videos to be listed on this page, TODO: If the list of videos grows, consider automating this like book.md. {% endcomment %} - ## Dart videos from Google A playlist of Google-produced videos, @@ -24,13 +22,3 @@ to the Dart session from Google I/O 2019. [Playlist: Dart videos](https://www.youtube.com/playlist?list={{page.dart-playlist-id}}) - - - -## Dart tutorial for beginners (by Smartherd) - -A community-provided series of tutorial videos about the Dart language. - - - -[Playlist: Dart tutorial for beginners](https://www.youtube.com/playlist?list={{page.smartherd-playlist-id}}) From 37c33219ddc4a070361775f0d59cb9002d52c57c Mon Sep 17 00:00:00 2001 From: Parker Lougheed Date: Mon, 14 Nov 2022 14:44:10 -0600 Subject: [PATCH 11/32] Better clarify option for named parameters in migration guide (#4364) Also adds a transition as the sentence was a bit confusing on its own. Fixes https://github.com/dart-lang/site-www/issues/4363 Co-authored-by: Anthony Sansone --- src/null-safety/migration-guide.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/null-safety/migration-guide.md b/src/null-safety/migration-guide.md index 10088e485..8122975f9 100644 --- a/src/null-safety/migration-guide.md +++ b/src/null-safety/migration-guide.md @@ -134,9 +134,10 @@ update its dependencies to null-safe versions: Most of the changes that your code needs to be null safe are easily predictable. For example, if a variable can be `null`, -[its type needs a `?` suffix][nullable type]. -A named parameter that shouldn't be nullable -needs to be [marked `required`][required]. +[its type needs a `?` suffix][nullable type]. +If a named parameter shouldn't be nullable, +mark it [`required`][required] +or give it a [default value][]. You have two options for migrating: @@ -151,6 +152,7 @@ You have two options for migrating: [nullable type]: /null-safety#creating-variables [required]: /null-safety/understanding-null-safety#required-named-parameters +[default value]: /guides/language/language-tour#default-parameters [migration tool]: #migration-tool [null safety FAQ]: /null-safety/faq From 2ec4dbbb86aef9f152c96af9089a9a99614d26ce Mon Sep 17 00:00:00 2001 From: Marya <111139605+MaryaBelanger@users.noreply.github.com> Date: Mon, 14 Nov 2022 15:09:34 -0800 Subject: [PATCH 12/32] Remove Intro to dart:io page (#4374) Intro to dart:io is outdated, and the important info it contained is available on other pages (the [library tour](https://dart.dev/guides/libraries/library-tour#dartio) and [Concurrency in Dart](https://dart.dev/guides/language/concurrency)) Part of #4042 --- .../lib/articles/io/io_file_system_test.dart | 8 - .../articles/io/io_http_server_file_test.dart | 43 -- .../lib/articles/io/io_http_server_test.dart | 10 - .../articles/io/io_process_stdio_test.dart | 16 - .../misc/lib/articles/io/io_process_test.dart | 9 - .../io/io_process_transform_test.dart | 17 - .../articles/io/io_random_access_test.dart | 21 - .../misc/lib/articles/io/io_stream_test.dart | 19 - .../misc/lib/articles/io/io_timer_test.dart | 7 - firebase.json | 1 + site-shared | 2 +- src/_articles/libraries/dart-io.md | 387 ------------------ src/_data/side-nav.yml | 2 - 13 files changed, 2 insertions(+), 540 deletions(-) delete mode 100644 examples/misc/lib/articles/io/io_file_system_test.dart delete mode 100644 examples/misc/lib/articles/io/io_http_server_file_test.dart delete mode 100644 examples/misc/lib/articles/io/io_http_server_test.dart delete mode 100644 examples/misc/lib/articles/io/io_process_stdio_test.dart delete mode 100644 examples/misc/lib/articles/io/io_process_test.dart delete mode 100644 examples/misc/lib/articles/io/io_process_transform_test.dart delete mode 100644 examples/misc/lib/articles/io/io_random_access_test.dart delete mode 100644 examples/misc/lib/articles/io/io_stream_test.dart delete mode 100644 examples/misc/lib/articles/io/io_timer_test.dart delete mode 100644 src/_articles/libraries/dart-io.md diff --git a/examples/misc/lib/articles/io/io_file_system_test.dart b/examples/misc/lib/articles/io/io_file_system_test.dart deleted file mode 100644 index e8671aa99..000000000 --- a/examples/misc/lib/articles/io/io_file_system_test.dart +++ /dev/null @@ -1,8 +0,0 @@ -// #docregion -import 'dart:convert'; -import 'dart:io'; - -void main() async { - var file = File(Platform.script.toFilePath()); - print(await (file.readAsString(encoding: ascii))); -} diff --git a/examples/misc/lib/articles/io/io_http_server_file_test.dart b/examples/misc/lib/articles/io/io_http_server_file_test.dart deleted file mode 100644 index d783cfb51..000000000 --- a/examples/misc/lib/articles/io/io_http_server_file_test.dart +++ /dev/null @@ -1,43 +0,0 @@ -// #docregion -import 'dart:io'; - -Future runServer(String basePath) async { - final server = await HttpServer.bind('127.0.0.1', 8082); - await for (final request in server) { - await handleRequest(basePath, request); - } -} - -Future handleRequest(String basePath, HttpRequest request) async { - final String path = request.uri.toFilePath(); - // PENDING: Do more security checks here. - final String resultPath = path == '/' ? '/index.html' : path; - final File file = File('$basePath$resultPath'); - if (await file.exists()) { - try { - await request.response.addStream(file.openRead()); - } catch (exception) { - print('Error happened: $exception'); - await sendInternalError(request.response); - } - } else { - await sendNotFound(request.response); - } -} - -Future sendInternalError(HttpResponse response) async { - response.statusCode = HttpStatus.internalServerError; - await response.close(); -} - -Future sendNotFound(HttpResponse response) async { - response.statusCode = HttpStatus.notFound; - await response.close(); -} - -void main() async { - // Compute base path for the request based on the location of the - // script, and then start the server. - final script = File(Platform.script.toFilePath()); - await runServer(script.parent.path); -} diff --git a/examples/misc/lib/articles/io/io_http_server_test.dart b/examples/misc/lib/articles/io/io_http_server_test.dart deleted file mode 100644 index de6f4be2a..000000000 --- a/examples/misc/lib/articles/io/io_http_server_test.dart +++ /dev/null @@ -1,10 +0,0 @@ -// #docregion -import 'dart:io'; - -void main() async { - final server = await HttpServer.bind('127.0.0.1', 8082); - await for (final request in server) { - request.response.write('Hello, world'); - await request.response.close(); - } -} diff --git a/examples/misc/lib/articles/io/io_process_stdio_test.dart b/examples/misc/lib/articles/io/io_process_stdio_test.dart deleted file mode 100644 index 6f7ecebfb..000000000 --- a/examples/misc/lib/articles/io/io_process_stdio_test.dart +++ /dev/null @@ -1,16 +0,0 @@ -// #docregion -import 'dart:io'; - -void main() async { - final output = File('output.txt').openWrite(); - Process process = await Process.start('ls', ['-l']); - - // Wait for the process to finish; get the exit code. - final exitCode = (await Future.wait([ - process.stdout.pipe(output), // Send stdout to file. - process.stderr.drain(), // Discard stderr. - process.exitCode - ]))[2]; - - print('exit code: $exitCode'); -} diff --git a/examples/misc/lib/articles/io/io_process_test.dart b/examples/misc/lib/articles/io/io_process_test.dart deleted file mode 100644 index 78b688d2b..000000000 --- a/examples/misc/lib/articles/io/io_process_test.dart +++ /dev/null @@ -1,9 +0,0 @@ -// #docregion -import 'dart:io'; - -void main() async { - // List all files in the current directory, - // in UNIX-like operating systems. - ProcessResult results = await Process.run('ls', ['-l']); - print(results.stdout); -} diff --git a/examples/misc/lib/articles/io/io_process_transform_test.dart b/examples/misc/lib/articles/io/io_process_transform_test.dart deleted file mode 100644 index eaccf49ce..000000000 --- a/examples/misc/lib/articles/io/io_process_transform_test.dart +++ /dev/null @@ -1,17 +0,0 @@ -// #docregion -import 'dart:convert'; -import 'dart:io'; - -void main() async { - final process = await Process.start('ls', ['-l']); - final lineStream = process.stdout - .transform(const Utf8Decoder()) - .transform(const LineSplitter()); - - await for (final line in lineStream) { - print(line); - } - - await process.stderr.drain(); - print('exit code: ${await process.exitCode}'); -} diff --git a/examples/misc/lib/articles/io/io_random_access_test.dart b/examples/misc/lib/articles/io/io_random_access_test.dart deleted file mode 100644 index 277ebf0df..000000000 --- a/examples/misc/lib/articles/io/io_random_access_test.dart +++ /dev/null @@ -1,21 +0,0 @@ -// #docregion -import 'dart:io'; - -void main() async { - final semicolon = ';'.codeUnitAt(0); - final result = []; - - final script = File(Platform.script.toFilePath()); - RandomAccessFile file = await script.open(mode: FileMode.read); - - // Deal with each byte. - while (true) { - final byte = await file.readByte(); - result.add(byte); - if (byte == semicolon) { - print(String.fromCharCodes(result)); - await file.close(); - break; - } - } -} diff --git a/examples/misc/lib/articles/io/io_stream_test.dart b/examples/misc/lib/articles/io/io_stream_test.dart deleted file mode 100644 index 15827aec4..000000000 --- a/examples/misc/lib/articles/io/io_stream_test.dart +++ /dev/null @@ -1,19 +0,0 @@ -// #docregion -import 'dart:io'; - -void main() async { - final result = []; - - Stream> stream = File(Platform.script.toFilePath()).openRead(); - final semicolon = ';'.codeUnitAt(0); - - await for (final data in stream) { - for (int i = 0; i < data.length; i++) { - result.add(data[i]); - if (data[i] == semicolon) { - print(String.fromCharCodes(result)); - return; - } - } - } -} diff --git a/examples/misc/lib/articles/io/io_timer_test.dart b/examples/misc/lib/articles/io/io_timer_test.dart deleted file mode 100644 index 7e2b4a5f2..000000000 --- a/examples/misc/lib/articles/io/io_timer_test.dart +++ /dev/null @@ -1,7 +0,0 @@ -// #docregion -import 'dart:async'; - -void main() { - Timer(const Duration(seconds: 1), () => print('timer')); - print('end of main'); -} diff --git a/firebase.json b/firebase.json index 9a5cf25f2..6e424e7df 100644 --- a/firebase.json +++ b/firebase.json @@ -55,6 +55,7 @@ { "source": "/articles/language/optional-types", "destination": "/faq#types", "type": 301 }, { "source": "/articles/libraries", "destination": "/articles", "type": 301 }, { "source": "/articles/libraries/converters-and-codecs", "destination": "/articles/archive/converters-and-codecs", "type": 301 }, + { "source": "/articles/libraries/dart-io", "destination": "/guides/libraries/library-tour#dartio", "type": 301 }, { "source": "/articles/libraries/zones", "destination": "/articles/archive/zones", "type": 301 }, { "source": "/articles/m*{,/**}", "destination": "/articles", "type": 301 }, { "source": "/articles/m1-language-changes{,/**}", "destination": "/guides/language/spec", "type": 301 }, diff --git a/site-shared b/site-shared index 3f55d0770..cbd9b3909 160000 --- a/site-shared +++ b/site-shared @@ -1 +1 @@ -Subproject commit 3f55d07704b43696ee36ac281a364d4f3faa19d2 +Subproject commit cbd9b3909699a817cb945a8faeec9b0730cb4fd7 diff --git a/src/_articles/libraries/dart-io.md b/src/_articles/libraries/dart-io.md deleted file mode 100644 index b70924310..000000000 --- a/src/_articles/libraries/dart-io.md +++ /dev/null @@ -1,387 +0,0 @@ ---- -title: "An introduction to the dart:io library" -description: An introduction to the Dart I/O library, which is aimed at code that runs in Flutter and the standalone Dart VM. -original-date: 2012-03-01 -date: 2021-06-03 -category: libraries ---- - -_Written by Mads Ager
-March 2012 (updated June 2021)_ - -The [dart:io]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-io/dart-io-library.html) library -is aimed at code that runs in Flutter and the standalone Dart VM. -In this article we will give you a feel for -what is currently possible with dart:io -by going through a couple of examples. - -{{site.alert.note}} - When writing a Flutter app, use - [Flutter-specific APIs]({{site.flutter-api}}) - instead of dart:io whenever possible. For example, use the - [Flutter asset support]({{site.flutter-docs}}/development/ui/assets-and-images) to load - images and other assets into your app. -{{site.alert.end}} - -Dart is a single-threaded programming language. -If an operation blocks the Dart thread, -the application makes no progress before that operation completes. -For scalability it is therefore crucial that no I/O operations block. -Instead of blocking on I/O operations, -dart:io uses an asynchronous programming model inspired by -[node.js,](https://nodejs.org) -[EventMachine,](https://github.com/eventmachine/eventmachine/wiki) and -[Twisted.](https://twisted.org/) - -## The Dart VM and the event loop - -Before we dive into asynchronous I/O operations, -it might be useful to explain how the standalone Dart VM operates. - -When executing a server-side application, -the Dart VM runs in an event loop with -an associated event queue of pending asynchronous operations. -The VM terminates when it has executed the current code to completion -and no more pending operations are in the queue. - -One simple way to add an event to the event queue is to -schedule a function to be called in the future. -You can do this by creating a -[Timer]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-async/Timer-class.html) object. -The following example registers a timer with the event queue -and then drops off the end of `main()`. -Because a pending operation is in the event queue, -the VM does not terminate at that point. -After one second, -the timer fires and the code in the argument callback executes. -Once that code executes to completion, -no more pending operations are in the event queue -and the VM terminates. - - -```dart -import 'dart:async'; - -void main() { - Timer(const Duration(seconds: 1), () => print('timer')); - print('end of main'); -} -``` - -Running this example at the command line, we get: - -```terminal -$ dart run timer.dart -end of main -timer -``` - -Had we made the timer repeating by using the -[Timer.periodic]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-async/Timer/Timer.periodic.html) constructor, -the VM would not terminate -and would continue to print out 'timer' every second. - -## File system access - -The dart:io library provides access to files and directories through the -[File]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-io/File-class.html) and -[Directory]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-io/Directory-class.html) classes. - -The following example prints its own source code. -To determine the location of the source code being executed, -we use the -[Platform]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-io/Platform-class.html) -class. - - - -```dart -import 'dart:convert'; -import 'dart:io'; - -void main() async { - var file = File(Platform.script.toFilePath()); - print(await (file.readAsString(encoding: ascii))); -} -``` - -Notice that the `readAsString()` method is asynchronous; -it returns a [Future]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-async/Future-class.html) -that returns the contents of the file -once the file has been read from the underlying system. -This asynchronicity allows the Dart thread to perform other work -while waiting for the I/O operation to complete. - -To illustrate more detailed file operations, -let's change the example to read the contents -only up to the first semicolon and then to print that. -You could do this in two ways: -either open the file for random access, -or open a -[Stream]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-async/Stream-class.html) -for the file and stream in the data. - -Here is a version that opens the file for random access operations. -The code opens the file for reading and then reads one byte at a time -until it encounters the char code for `;`. - - -```dart -import 'dart:io'; - -void main() async { - final semicolon = ';'.codeUnitAt(0); - final result = []; - - final script = File(Platform.script.toFilePath()); - RandomAccessFile file = await script.open(mode: FileMode.read); - - // Deal with each byte. - while (true) { - final byte = await file.readByte(); - result.add(byte); - if (byte == semicolon) { - print(String.fromCharCodes(result)); - await file.close(); - break; - } - } -} -``` - -When you see a use of `async` or `await`, you are seeing a Future in action. -Both the `open()` and `readByte()` methods return a Future object. - -This code is, of course, -a very simple use of random-access operations. -Operations are available for writing, -seeking to a given position, truncating, and so on. - -Let's implement a version using a stream. -The following code opens the file for reading presenting the content -as a stream of lists of bytes. Like all streams in Dart you listen on -this stream (using `await for`) and the data is given in chunks. - - -```dart -import 'dart:io'; - -void main() async { - final result = []; - - Stream> stream = File(Platform.script.toFilePath()).openRead(); - final semicolon = ';'.codeUnitAt(0); - - await for (final data in stream) { - for (int i = 0; i < data.length; i++) { - result.add(data[i]); - if (data[i] == semicolon) { - print(String.fromCharCodes(result)); - return; - } - } - } -} -``` - -The stream subscription is implicitly handled by `await for`. -Exiting the `await for` statement—using `break`, `return`, -or an uncaught exception—cancels the subscription. - -`Stream>` is used in multiple places in dart:io: -when working with stdin, files, sockets, HTTP connections, and so on. -Similarly, [IOSink]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-io/IOSink-class.html) objects -are used to stream data to -stdout, files, sockets, HTTP connections, and so on. - -## Interacting with processes - -For the simple case, use -[Process.run()]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-io/Process/run.html) -to run a process -and collect its output. Use `run()` when you don't -need interactive control over the process. - - -```dart -import 'dart:io'; - -void main() async { - // List all files in the current directory, - // in UNIX-like operating systems. - ProcessResult results = await Process.run('ls', ['-l']); - print(results.stdout); -} -``` - -You can also start a process by creating a -[Process]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-io/Process-class.html) object -using -[Process.start().]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-io/Process/start.html) - -Once you have a Process object you can interact with the process -by writing data to its stdin sink, -reading data from its stderr and stdout streams, -and killing the process. -When the process exits, the `exitCode` future completes with -the exit code of the process. - -The following example runs `ls -l` in a separate process -and prints the output and the exit code for the process to stdout. -Since we are interested in getting lines, -we use a -[Utf8Decoder]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-convert/Utf8Decoder-class.html) -(which decodes chunks of bytes into strings) followed by a -[LineSplitter]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-convert/LineSplitter-class.html) -(which splits the strings at line boundaries). - - -```dart -import 'dart:convert'; -import 'dart:io'; - -void main() async { - final process = await Process.start('ls', ['-l']); - final lineStream = process.stdout - .transform(const Utf8Decoder()) - .transform(const LineSplitter()); - - await for (final line in lineStream) { - print(line); - } - - await process.stderr.drain(); - print('exit code: ${await process.exitCode}'); -} -``` - -Notice that `exitCode` can complete before all of the lines of output -have been processed. Also note -that we do not explicitly close the process. In order to -not leak resources we have to listen to both the stderr and stdout -streams. We use `await for` to listen to stdout, -and `stderr.drain()` to listen to (and discard) stderr. - -Instead of printing the output to stdout, -we can use the streaming classes -to pipe the output of the process to a file. - - -```dart -import 'dart:io'; - -void main() async { - final output = File('output.txt').openWrite(); - Process process = await Process.start('ls', ['-l']); - - // Wait for the process to finish; get the exit code. - final exitCode = (await Future.wait([ - process.stdout.pipe(output), // Send stdout to file. - process.stderr.drain(), // Discard stderr. - process.exitCode - ]))[2]; - - print('exit code: $exitCode'); -} -``` - - -## Writing web servers - -dart:io makes it easy to write HTTP servers and clients. -To write a simple web server, -all you have to do is create an -[HttpServer]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-io/HttpServer-class.html) -and hook up a listener (using `await for`) to its stream of `HttpRequest`s. - -Here is a simple web server -that just answers 'Hello, world' to any request. - - -```dart -import 'dart:io'; - -void main() async { - final server = await HttpServer.bind('127.0.0.1', 8082); - await for (final request in server) { - request.response.write('Hello, world'); - await request.response.close(); - } -} -``` - -Running this application -and pointing your browser to 'http://127.0.0.1:8082' -gives you 'Hello, world' as expected. - -Let's add a bit more and actually serve files. -The base path for every file that we serve will be -the location of the script. -If no path is specified in a request we will serve index.html. -For a request with a path, -we will attempt to find the file and serve it. -If the file is not found we will respond with a '404 Not Found' status. -We make use of the streaming interface -to pipe all the data read from a file directly to the response stream. - -```dart -import 'dart:io'; - -Future runServer(String basePath) async { - final server = await HttpServer.bind('127.0.0.1', 8082); - await for (final request in server) { - await handleRequest(basePath, request); - } -} - -Future handleRequest(String basePath, HttpRequest request) async { - final String path = request.uri.toFilePath(); - // PENDING: Do more security checks here. - final String resultPath = path == '/' ? '/index.html' : path; - final File file = File('$basePath$resultPath'); - if (await file.exists()) { - try { - await request.response.addStream(file.openRead()); - } catch (exception) { - print('Error happened: $exception'); - await sendInternalError(request.response); - } - } else { - await sendNotFound(request.response); - } -} - -Future sendInternalError(HttpResponse response) async { - response.statusCode = HttpStatus.internalServerError; - await response.close(); -} - -Future sendNotFound(HttpResponse response) async { - response.statusCode = HttpStatus.notFound; - await response.close(); -} - -void main() async { - // Compute base path for the request based on the location of the - // script, and then start the server. - final script = File(Platform.script.toFilePath()); - await runServer(script.parent.path); -} -``` - -Writing HTTP clients is very similar to using the -[HttpClient]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-io/HttpClient-class.html) -class. - - -## Feature requests welcome - -The dart:io library is already capable of performing a lot of tasks. -For example, the [pub.dev site]({{site.pub}}) uses dart:io. - -Please give dart:io a spin and let us know what you think. -Feature requests are very welcome! -When you file a bug or feature request, -use [dartbug.com.](https://dartbug.com) -To find reported issues, search for the -[library-io label.](https://github.com/dart-lang/sdk/issues?q=label%3Alibrary-io) diff --git a/src/_data/side-nav.yml b/src/_data/side-nav.yml index 809d5a00c..f5cfe1b59 100644 --- a/src/_data/side-nav.yml +++ b/src/_data/side-nav.yml @@ -96,8 +96,6 @@ permalink: /guides/libraries/library-tour - title: Articles children: - - title: Intro to dart:io - permalink: /articles/libraries/dart-io - title: Creating streams permalink: /articles/libraries/creating-streams From 9cf61bb8906b5959122c00ab3623cf08c1428f94 Mon Sep 17 00:00:00 2001 From: Parker Lougheed Date: Mon, 14 Nov 2022 18:05:36 -0600 Subject: [PATCH 13/32] Update custom metadata code example in language tour (#4367) - Remove unnecessary library annotation as it is only recommended if you have annotations or doc comments - Remove import as it doesn't add to example - Switch name to Dash --- examples/misc/lib/language_tour/metadata/misc.dart | 6 ++++-- examples/misc/lib/language_tour/metadata/todo.dart | 2 -- src/_guides/language/language-tour.md | 8 ++------ 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/examples/misc/lib/language_tour/metadata/misc.dart b/examples/misc/lib/language_tour/metadata/misc.dart index b61a2b228..7585221cd 100644 --- a/examples/misc/lib/language_tour/metadata/misc.dart +++ b/examples/misc/lib/language_tour/metadata/misc.dart @@ -1,6 +1,8 @@ import 'todo.dart'; -@Todo('seth', 'make this do something') +// #docregion +@Todo('Dash', 'Implement this function') void doSomething() { - print('do something'); + print('Do something'); } +// #enddocregion diff --git a/examples/misc/lib/language_tour/metadata/todo.dart b/examples/misc/lib/language_tour/metadata/todo.dart index 0a23b8a65..a8531d119 100644 --- a/examples/misc/lib/language_tour/metadata/todo.dart +++ b/examples/misc/lib/language_tour/metadata/todo.dart @@ -1,5 +1,3 @@ -library todo; - class Todo { final String who; final String what; diff --git a/src/_guides/language/language-tour.md b/src/_guides/language/language-tour.md index 84d264d4a..9fde7ed64 100644 --- a/src/_guides/language/language-tour.md +++ b/src/_guides/language/language-tour.md @@ -4671,8 +4671,6 @@ defining a `@Todo` annotation that takes two arguments: ```dart -library todo; - class Todo { final String who; final String what; @@ -4685,11 +4683,9 @@ And here’s an example of using that `@Todo` annotation: ```dart -import 'todo.dart'; - -@Todo('seth', 'make this do something') +@Todo('Dash', 'Implement this function') void doSomething() { - print('do something'); + print('Do something'); } ``` From f19c6f6b70101790ea1f83ede033af16f84aafc6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Nov 2022 04:11:05 -0600 Subject: [PATCH 14/32] Bump github/codeql-action from 2.1.31 to 2.1.32 (#4377) --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 688839230..7fcd3e18e 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -33,7 +33,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@c3b6fce4ee2ca25bc1066aa3bf73962fda0e8898 + uses: github/codeql-action/init@4238421316c33d73aeea2801274dd286f157c2bb with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -44,7 +44,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@c3b6fce4ee2ca25bc1066aa3bf73962fda0e8898 + uses: github/codeql-action/autobuild@4238421316c33d73aeea2801274dd286f157c2bb # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -58,4 +58,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@c3b6fce4ee2ca25bc1066aa3bf73962fda0e8898 + uses: github/codeql-action/analyze@4238421316c33d73aeea2801274dd286f157c2bb diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 5aef51b2e..5d5de4989 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -49,6 +49,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@c3b6fce4ee2ca25bc1066aa3bf73962fda0e8898 + uses: github/codeql-action/upload-sarif@4238421316c33d73aeea2801274dd286f157c2bb with: sarif_file: results.sarif From 18f79c883427ec2cd7eac7bcc4cf4c2db371e1a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Nov 2022 04:22:52 -0600 Subject: [PATCH 15/32] Bump site-shared from `cbd9b39` to `3f55d07` (#4378) Bumps [site-shared](https://github.com/dart-lang/site-shared) from `cbd9b39` to `3f55d07`.
Commits

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site-shared | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site-shared b/site-shared index cbd9b3909..3f55d0770 160000 --- a/site-shared +++ b/site-shared @@ -1 +1 @@ -Subproject commit cbd9b3909699a817cb945a8faeec9b0730cb4fd7 +Subproject commit 3f55d07704b43696ee36ac281a364d4f3faa19d2 From 9d9376afae8e77a1cbe2162a2a13efdca76cbd4d Mon Sep 17 00:00:00 2001 From: Parker Lougheed Date: Tue, 15 Nov 2022 13:14:59 -0600 Subject: [PATCH 16/32] Mention generate constructor in null safety FAQ (#4368) Fixes #2837 Co-authored-by: Anthony Sansone --- src/null-safety/faq.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/null-safety/faq.md b/src/null-safety/faq.md index 5a509fea8..c1f6671f5 100644 --- a/src/null-safety/faq.md +++ b/src/null-safety/faq.md @@ -285,6 +285,21 @@ _jellyPoints = [ ]; {% endprettify %} +To generate a fixed-length list, +use the [`List.generate`][] constructor +with the `growable` parameter set to `false`: + +```dart +_jellyPoints = List.generate(jellyMax, (_) => Vec2D(), growable: false); +``` + +[`List.generate`]: {{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-core/List/List.generate.html + +{% comment %} + Would preferably suggest a language syntax here, + which is being suggested in https://github.com/dart-lang/language/issues/2477. +{% endcomment %} + ## What happened to the default List constructor? You may encounter this error: From adc5ce1c215d3fe094332e2e45ba804914800596 Mon Sep 17 00:00:00 2001 From: Parker Lougheed Date: Tue, 15 Nov 2022 16:19:45 -0600 Subject: [PATCH 17/32] Move default value for optional parameters discussion to each individual section (#4366) Currently setting default values for optional named and positional parameters was separated, but it is pretty core to each topic, so this PR moves the discussion of default values to each of the parameter sections. This helps the examples make a bit more sense as they are contextualized. I've also removed the mention of migrating from `=` to `:` because it was added over 6 years ago, most code already uses `:`, the extra mention is large and potentially confusing (and don't want to duplicate it in this new layout), and in Dart 2.19 the old syntax will become a warning anyway. Also removes the mention of how list and maps can be passed. It doesn't talk about sets or other constant objects which can be passed as well and isn't super relevant to the goals of these sections. We should instead expand on our documentation of const (https://github.com/dart-lang/site-www/issues/4350) elsewhere and link to that. Overall: - Moves default value discussion to named and optional positional sections instead of isolated - Better clarifies the nullable types and when they are needed, as well as how `null` is the default default value - Moves discussion of named parameters anywhere to end - Removes mention of old `=` syntax - Removes mention of how list and maps can be passed as don't want to duplicate it and it is better documented by const documentation elsewhere Fixes https://github.com/dart-lang/site-www/issues/3737 Co-authored-by: Anthony Sansone --- .../misc/lib/language_tour/functions.dart | 21 +-- src/_guides/language/language-tour.md | 141 +++++++----------- 2 files changed, 59 insertions(+), 103 deletions(-) diff --git a/examples/misc/lib/language_tour/functions.dart b/examples/misc/lib/language_tour/functions.dart index 190a85689..3d283cb4f 100644 --- a/examples/misc/lib/language_tour/functions.dart +++ b/examples/misc/lib/language_tour/functions.dart @@ -55,21 +55,6 @@ void miscDeclAnalyzedButNotTested() { // #enddocregion named-parameter-default-values } - { - // #docregion list-map-default-function-param - void doStuff( - {List list = const [1, 2, 3], - Map gifts = const { - 'first': 'paper', - 'second': 'cotton', - 'third': 'leather' - }}) { - print('list: $list'); - print('gifts: $gifts'); - } - // #enddocregion list-map-default-function-param - } - { // #docregion function-as-param void printElement(int element) { @@ -95,3 +80,9 @@ class Scrollbar extends Widget { const Scrollbar({super.key, required Widget child}); // #enddocregion required-named-parameters } + +class ScrollbarTwo extends Widget { + // #docregion required-named-parameters-nullable + const ScrollbarTwo({super.key, required Widget? child}); + // #enddocregion required-named-parameters-nullable +} diff --git a/src/_guides/language/language-tour.md b/src/_guides/language/language-tour.md index 9fde7ed64..47b4f8b48 100644 --- a/src/_guides/language/language-tour.md +++ b/src/_guides/language/language-tour.md @@ -1315,7 +1315,11 @@ unless they're explicitly marked as `required`. When defining a function, use {param1, param2, …} -to specify named parameters: +to specify named parameters. +If you don't provide a default value +or mark a named parameter as `required`, +their types must be nullable +as their default value will be `null`: ```dart @@ -1333,45 +1337,63 @@ For example: enableFlags(bold: true, hidden: false); ``` -Although it often makes sense to place positional arguments first, -named arguments can be placed anywhere in the argument list -when it suits your API: + +To define a default value for a named parameter besides `null`, +use `=` to specify a default value. +The specified value must be a compile-time constant. +For example: - + ```dart -repeat(times: 2, () { - ... -}); -``` +/// Sets the [bold] and [hidden] flags ... +void enableFlags({bool bold = false, bool hidden = false}) {...} -{{site.alert.tip}} - If a parameter is optional but can't be `null`, - provide a [default value](#default-parameter-values). -{{site.alert.end}} +// bold will be true; hidden will be false. +enableFlags(bold: true); +``` -Although named parameters are a kind of optional parameter, -you can annotate them with `required` to indicate -that the parameter is mandatory—that users -must provide a value for the parameter. -For example: +If you instead want a named parameter to be mandatory, +requiring callers to provide a value for the parameter, +annotate them with `required`: -{% prettify dart tag=pre+code %} +```dart const Scrollbar({super.key, [!required!] Widget child}); -{% endprettify %} +``` If someone tries to create a `Scrollbar` without specifying the `child` argument, then the analyzer reports an issue. -{% comment %} -NULLSAFE: Rewrite this section. -{% endcomment %} +{{site.alert.note}} + A parameter marked as `required` + can still be nullable: + + + ```dart + const Scrollbar({super.key, required [!Widget?!] child}); + ``` +{{site.alert.end}} + +You might want to place positional arguments first, +but Dart doesn't require it. +Dart allows named arguments to be placed anywhere in the +argument list when it suits your API: + + +```dart +repeat(times: 2, () { + ... +}); +``` #### Optional positional parameters -Wrapping a set of function parameters in `[]` marks them as optional -positional parameters: +Wrapping a set of function parameters in `[]` +marks them as optional positional parameters. +If you don't provide a default value, +their types must be nullable +as their default value will be `null`: ```dart @@ -1384,8 +1406,8 @@ String say(String from, String msg, [String? device]) { } ``` -Here’s an example of calling this function without the optional -parameter: +Here’s an example of calling this function +without the optional parameter: ```dart @@ -1400,45 +1422,10 @@ assert(say('Bob', 'Howdy', 'smoke signal') == 'Bob says Howdy with a smoke signal'); ``` - -#### Default parameter values - -Your function can use `=` to define default values for optional parameters, -both named and positional. The default values must be compile-time constants. -If no default value is provided, the default value is `null`. - -Here's an example of setting default values for named parameters: - - -```dart -/// Sets the [bold] and [hidden] flags ... -void enableFlags({bool bold = false, bool hidden = false}) {...} - -// bold will be true; hidden will be false. -enableFlags(bold: true); -``` - -{{site.alert.secondary}} - **Deprecation note:** Old code might use a colon (`:`) instead of `=` - to specify default values of named parameters. - The reason is that originally, only `:` was supported for named parameters. - That support is deprecated and will be removed, - so we recommend that you **[use `=` to specify default values.][use =]** - - If you have the [`prefer_equal_for_default_values`][] linter rule enabled, - you can use [`dart fix`][] to migrate to the suggested `=` syntax. - - [use =]: /guides/language/effective-dart/usage#do-use--to-separate-a-named-parameter-from-its-default-value - [`prefer_equal_for_default_values`]: /tools/linter-rules#prefer_equal_for_default_values - [`dart fix`]: /tools/dart-fix -{{site.alert.end}} - -{% comment %} -TODO #2950: Update if/when we drop support for `:`. -See `defaultNamedParameter` in the language spec. -{% endcomment %} - -The next example shows how to set default values for positional parameters: +To define a default value for an optional positional parameter besides `null`, +use `=` to specify a default value. +The specified value must be a compile-time constant. +For example: ```dart @@ -1450,28 +1437,6 @@ String say(String from, String msg, [String device = 'carrier pigeon']) { assert(say('Bob', 'Howdy') == 'Bob says Howdy with a carrier pigeon'); ``` -You can also pass lists or maps as default values. -The following example defines a function, `doStuff()`, -that specifies a default list for the `list` -parameter and a default map for the `gifts` parameter. -{% comment %} -The function is called three times with different values. Click **Run** to see -list and map default values in action. -{% endcomment %} - - -```dart -void doStuff( - {List list = const [1, 2, 3], - Map gifts = const { - 'first': 'paper', - 'second': 'cotton', - 'third': 'leather' - }}) { - print('list: $list'); - print('gifts: $gifts'); -} -``` ### The main() function From 449ede282db079ff37d556c48fb45b7495c1b0d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Nov 2022 13:26:03 -0600 Subject: [PATCH 18/32] Bump ruby from `ed50d57` to `5d413e3` (#4380) Bumps ruby from `ed50d57` to `5d413e3`. [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ruby&package-manager=docker&previous-version=3-slim-bullseye&new-version=3-slim-bullseye)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index cf7932f91..16852047a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3-slim-bullseye@sha256:ed50d5719f8ecd0bae4d26bc91672f130463d7be05b67433ab595af39da1a95d as base +FROM ruby:3-slim-bullseye@sha256:5d413e301f37cbe63a54dadded2f347496165c1de0dbe342d1f0f0d47e25b2be as base ENV DEBIAN_FRONTEND=noninteractive ENV TZ=US/Pacific From 1ed53d58c73c60296b8717e17a1362be563a0b7e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Nov 2022 04:22:47 -0600 Subject: [PATCH 19/32] Bump github/codeql-action from 2.1.32 to 2.1.33 (#4381) --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 7fcd3e18e..dad46b4b1 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -33,7 +33,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@4238421316c33d73aeea2801274dd286f157c2bb + uses: github/codeql-action/init@678fc3afe258fb2e0cdc165ccf77b85719de7b3c with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -44,7 +44,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@4238421316c33d73aeea2801274dd286f157c2bb + uses: github/codeql-action/autobuild@678fc3afe258fb2e0cdc165ccf77b85719de7b3c # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -58,4 +58,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@4238421316c33d73aeea2801274dd286f157c2bb + uses: github/codeql-action/analyze@678fc3afe258fb2e0cdc165ccf77b85719de7b3c diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 5d5de4989..5433fd1ee 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -49,6 +49,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@4238421316c33d73aeea2801274dd286f157c2bb + uses: github/codeql-action/upload-sarif@678fc3afe258fb2e0cdc165ccf77b85719de7b3c with: sarif_file: results.sarif From b8069034fc4c46cb8518efe7a5dfe9724f3dbac6 Mon Sep 17 00:00:00 2001 From: Parker Lougheed Date: Thu, 17 Nov 2022 15:39:28 -0600 Subject: [PATCH 20/32] Fix build for new dev analysis changes (#4384) Ignores some new hints where they are not relevant due to purposely showcasing that behavior or having dead code. Also updates the diagnostic message for one updated in the dev branch. --- examples/analysis/analyzer-results-dev.txt | 2 +- examples/misc/lib/effective_dart/usage_bad.dart | 1 + examples/misc/lib/effective_dart/usage_good.dart | 2 +- examples/misc/test/library_tour/io_test.dart | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/analysis/analyzer-results-dev.txt b/examples/analysis/analyzer-results-dev.txt index ff7e794b1..9f03156b0 100644 --- a/examples/analysis/analyzer-results-dev.txt +++ b/examples/analysis/analyzer-results-dev.txt @@ -1,7 +1,7 @@ Analyzing analysis... error - lib/strict_modes.dart:15:7 - The argument type 'dynamic' can't be assigned to the parameter type 'List'. - argument_type_not_assignable - info - lib/lint.dart:9:19 - Avoid empty statements. - empty_statements + info - lib/lint.dart:9:19 - Unnecessary empty statement. Try removing the empty statement or restructuring the code. - empty_statements info - lib/lint.dart:17:7 - Close instances of `dart.core.Sink`. - close_sinks info - lib/strict_modes.dart:22:17 - The type argument(s) of 'Map' can't be inferred. Use explicit type argument(s) for 'Map'. - inference_failure_on_collection_literal info - lib/strict_modes.dart:33:3 - The generic type 'List' should have explicit type arguments but doesn't. Use explicit type arguments for 'List'. - strict_raw_type diff --git a/examples/misc/lib/effective_dart/usage_bad.dart b/examples/misc/lib/effective_dart/usage_bad.dart index 7ce04ccc6..028c02148 100644 --- a/examples/misc/lib/effective_dart/usage_bad.dart +++ b/examples/misc/lib/effective_dart/usage_bad.dart @@ -6,6 +6,7 @@ // ignore_for_file: avoid_function_literals_in_foreach_calls, prefer_function_declarations_over_variables // ignore_for_file: prefer_adjacent_string_concatenation, prefer_is_not_empty, prefer_interpolation_to_compose_strings // ignore_for_file: unnecessary_this, always_declare_return_types, no_leading_underscores_for_local_identifiers +// ignore_for_file: deprecated_colon_for_default_value import 'dart:async'; import 'dart:io'; import 'dart:math'; diff --git a/examples/misc/lib/effective_dart/usage_good.dart b/examples/misc/lib/effective_dart/usage_good.dart index d35ca042d..8c89282bb 100644 --- a/examples/misc/lib/effective_dart/usage_good.dart +++ b/examples/misc/lib/effective_dart/usage_good.dart @@ -1,7 +1,7 @@ // ignore_for_file: type_annotate_public_apis, unused_element, unused_local_variable // ignore_for_file: prefer_function_declarations_over_variables, strict_raw_type, // ignore_for_file: prefer_initializing_formals, prefer_typing_uninitialized_variables -// ignore_for_file: use_super_parameters +// ignore_for_file: use_super_parameters, dead_code import 'dart:async'; import 'dart:io'; import 'dart:math'; diff --git a/examples/misc/test/library_tour/io_test.dart b/examples/misc/test/library_tour/io_test.dart index b2a623ed3..545dae4c7 100644 --- a/examples/misc/test/library_tour/io_test.dart +++ b/examples/misc/test/library_tour/io_test.dart @@ -58,7 +58,7 @@ void main() { } // #enddocregion try-catch - expect(main, prints(startsWith('FileSystemException'))); + expect(main, prints(contains('Cannot open file'))); }); test('read-from-stream', () { From f74289a27b4063aff6adefc9e0e650c69dfbd122 Mon Sep 17 00:00:00 2001 From: Parker Lougheed Date: Thu, 17 Nov 2022 16:30:22 -0600 Subject: [PATCH 21/32] Remove jobs/hiring note from banner (#4385) --- src/_includes/banner.html | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/_includes/banner.html b/src/_includes/banner.html index 6ac27468f..b60c12581 100644 --- a/src/_includes/banner.html +++ b/src/_includes/banner.html @@ -1,8 +1,6 @@ {% comment %}Drop the div .alert classes to revert to the default banner styling.{% endcomment -%} \ No newline at end of file From 0ffdb13214bab16c3ef114f5559e4889991a0d6f Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 17 Nov 2022 14:48:12 -0800 Subject: [PATCH 22/32] Drop referenced to discontinued firebase package (#4386) --- src/web/js-interop.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/web/js-interop.md b/src/web/js-interop.md index 0a0d080d6..af264758d 100644 --- a/src/web/js-interop.md +++ b/src/web/js-interop.md @@ -15,13 +15,10 @@ For help using the `js` package, see the following: * [pub.dev site page][js] * [API reference][js-api] * Packages that use the `js` package: - * [firebase][] is a good example of providing a Dart-like API - to a JavaScript library. * [sass][] is an example of a more unusual use case: providing a way for JavaScript code to call Dart code. [js]: {{site.pub-pkg}}/js [js-api]: {{site.pub-api}}/js -[firebase]: {{site.pub-pkg}}/firebase [sass]: {{site.pub-pkg}}/sass From e6aeb087e4217415a2a88128db696f0bca2e75af Mon Sep 17 00:00:00 2001 From: Parker Lougheed Date: Thu, 17 Nov 2022 19:09:47 -0600 Subject: [PATCH 23/32] Update linter rules for bad-good consistency and linter 1.30 (#4383) Updated from https://github.com/dart-lang/linter/commit/46a65ff1a9bfe77f509cd52d5e2f76eb09ab2e6e --- src/_data/linter_rules.json | 138 ++++++++++++++++++------------------ 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/src/_data/linter_rules.json b/src/_data/linter_rules.json index c6ea03c0e..17656c04f 100644 --- a/src/_data/linter_rules.json +++ b/src/_data/linter_rules.json @@ -7,7 +7,7 @@ "incompatible": [], "sets": [], "fixStatus": "hasFix", - "details": "**DO** avoid relative imports for files in `lib/`.\n\nWhen mixing relative and absolute imports it's possible to create confusion\nwhere the same member gets imported in two different ways. One way to avoid\nthat is to ensure you consistently use absolute imports for files within the\n`lib/` directory.\n\nThis is the opposite of 'prefer_relative_imports'.\n\nYou can also use 'avoid_relative_lib_imports' to disallow relative imports of\nfiles within `lib/` directory outside of it (for example `test/`).\n\n**GOOD:**\n\n```dart\nimport 'package:foo/bar.dart';\n\nimport 'package:foo/baz.dart';\n\nimport 'package:foo/src/baz.dart';\n...\n```\n\n**BAD:**\n\n```dart\nimport 'baz.dart';\n\nimport 'src/bag.dart'\n\nimport '../lib/baz.dart';\n\n...\n```\n\n", + "details": "**DO** avoid relative imports for files in `lib/`.\n\nWhen mixing relative and absolute imports it's possible to create confusion\nwhere the same member gets imported in two different ways. One way to avoid\nthat is to ensure you consistently use absolute imports for files within the\n`lib/` directory.\n\nThis is the opposite of 'prefer_relative_imports'.\n\nYou can also use 'avoid_relative_lib_imports' to disallow relative imports of\nfiles within `lib/` directory outside of it (for example `test/`).\n\n**BAD:**\n```dart\nimport 'baz.dart';\n\nimport 'src/bag.dart'\n\nimport '../lib/baz.dart';\n\n...\n```\n\n**GOOD:**\n```dart\nimport 'package:foo/bar.dart';\n\nimport 'package:foo/baz.dart';\n\nimport 'package:foo/src/baz.dart';\n...\n```\n\n", "sinceDartSdk": "2.10.0", "sinceLinter": "0.1.118" }, @@ -65,7 +65,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "**DO** avoid relative imports for files in `lib/`.\n\nWhen mixing relative and absolute imports it's possible to create confusion\nwhere the same member gets imported in two different ways. An easy way to avoid\nthat is to ensure you have no relative imports that include `lib/` in their\npaths.\n\nYou can also use 'always_use_package_imports' to disallow relative imports\nbetween files within `lib/`.\n\n**GOOD:**\n\n```dart\nimport 'package:foo/bar.dart';\n\nimport 'baz.dart';\n\n...\n```\n\n**BAD:**\n\n```dart\nimport 'package:foo/bar.dart';\n\nimport '../lib/baz.dart';\n\n...\n```\n\n", + "details": "**DO** avoid relative imports for files in `lib/`.\n\nWhen mixing relative and absolute imports it's possible to create confusion\nwhere the same member gets imported in two different ways. An easy way to avoid\nthat is to ensure you have no relative imports that include `lib/` in their\npaths.\n\nYou can also use 'always_use_package_imports' to disallow relative imports\nbetween files within `lib/`.\n\n**BAD:**\n```dart\nimport 'package:foo/bar.dart';\n\nimport '../lib/baz.dart';\n\n...\n```\n\n**GOOD:**\n```dart\nimport 'package:foo/bar.dart';\n\nimport 'baz.dart';\n\n...\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.44" }, @@ -167,7 +167,7 @@ "incompatible": [], "sets": [], "fixStatus": "needsEvaluation", - "details": "**DON'T** invoke certain collection method with an argument with an unrelated\ntype.\n\nDoing this will invoke `==` on the collection's elements and most likely will\nreturn `false`.\n\nAn argument passed to a collection method should relate to the collection type\nas follows:\n\n* an argument to `Iterable.contains` should be related to `E`\n* an argument to `List.remove` should be related to `E`\n* an argument to `Map.containsKey` should be related to `K`\n* an argument to `Map.containsValue` should be related to `V`\n* an argument to `Map.remove` should be related to `K`\n* an argument to `Map.[]` should be related to `K`\n* an argument to `Queue.remove` should be related to `E`\n* an argument to `Set.containsAll` should be related to `Iterable`\n* an argument to `Set.difference` should be related to `Set`\n* an argument to `Set.intersection` should be related to `Set`\n* an argument to `Set.lookup` should be related to `E`\n* an argument to `Set.remove` should be related to `E`\n* an argument to `Set.removeAll` should be related to `Iterable`\n* an argument to `Set.retainAll` should be related to `Iterable`\n\n**BAD:**\n```dart\nvoid someFunction() {\n var list = [];\n if (list.contains('1')) print('someFunction'); // LINT\n}\n```\n\n**BAD:**\n```dart\nvoid someFunction() {\n var set = {};\n set.removeAll({'1'}); // LINT\n}\n```\n\n**GOOD:**\n```dart\nvoid someFunction() {\n var list = [];\n if (list.contains(1)) print('someFunction'); // OK\n}\n```\n\n**GOOD:**\n```dart\nvoid someFunction() {\n var set = {};\n set.removeAll({1}); // OK\n}\n```\n\n", + "details": "**DON'T** invoke certain collection method with an argument with an unrelated\ntype.\n\nDoing this will invoke `==` on the collection's elements and most likely will\nreturn `false`.\n\nAn argument passed to a collection method should relate to the collection type\nas follows:\n\n* an argument to `Iterable.contains` should be related to `E`\n* an argument to `List.remove` should be related to `E`\n* an argument to `Map.containsKey` should be related to `K`\n* an argument to `Map.containsValue` should be related to `V`\n* an argument to `Map.remove` should be related to `K`\n* an argument to `Map.[]` should be related to `K`\n* an argument to `Queue.remove` should be related to `E`\n* an argument to `Set.lookup` should be related to `E`\n* an argument to `Set.remove` should be related to `E`\n\n**BAD:**\n```dart\nvoid someFunction() {\n var list = [];\n if (list.contains('1')) print('someFunction'); // LINT\n}\n```\n\n**BAD:**\n```dart\nvoid someFunction() {\n var set = {};\n set.remove('1'); // LINT\n}\n```\n\n**GOOD:**\n```dart\nvoid someFunction() {\n var list = [];\n if (list.contains(1)) print('someFunction'); // OK\n}\n```\n\n**GOOD:**\n```dart\nvoid someFunction() {\n var set = {};\n set.remove(1); // OK\n}\n```\n\n", "sinceDartSdk": "Unreleased", "sinceLinter": "1.29.0" }, @@ -179,7 +179,7 @@ "incompatible": [], "sets": [], "fixStatus": "needsEvaluation", - "details": "**DO** reference only in scope identifiers in doc comments.\n\nIf you surround things like variable, method, or type names in square brackets,\nthen [`dart doc`](https://dart.dev/tools/dart-doc) will look\nup the name and link to its docs. For this all to work, ensure that all\nidentifiers in docs wrapped in brackets are in scope.\n\nFor example,\n\n**GOOD:**\n```dart\n/// Return the larger of [a] or [b].\nint max_int(int a, int b) { ... }\n```\n\nOn the other hand, assuming `outOfScopeId` is out of scope:\n\n**BAD:**\n```dart\n/// Return true if [value] is larger than [outOfScopeId].\nbool isOutOfRange(int value) { ... }\n```\n\nNote that the square bracket comment format is designed to allow \ncomments to refer to declarations using a fairly natural format \nbut does not allow *arbitrary expressions*. In particular, code \nreferences within square brackets can consist of either\n\n- a single identifier where the identifier is any identifier in scope for the comment (see the spec for what is in scope in doc comments),\n- two identifiers separated by a period where the first identifier is the name of a class that is in scope and the second is the name of a member declared in the class,\n- a single identifier followed by a pair of parentheses where the identifier is the name of a class that is in scope (used to refer to the unnamed constructor for the class), or\n- two identifiers separated by a period and followed by a pair of parentheses where the first identifier is the name of a class that is in scope and the second is the name of a named constructor (not strictly necessary, but allowed for consistency).\n\n", + "details": "**DO** reference only in scope identifiers in doc comments.\n\nIf you surround things like variable, method, or type names in square brackets,\nthen [`dart doc`](https://dart.dev/tools/dart-doc) will look\nup the name and link to its docs. For this all to work, ensure that all\nidentifiers in docs wrapped in brackets are in scope.\n\nFor example, assuming `outOfScopeId` is out of scope:\n\n**BAD:**\n```dart\n/// Return true if [value] is larger than [outOfScopeId].\nbool isOutOfRange(int value) { ... }\n```\n\n**GOOD:**\n```dart\n/// Return the larger of [a] or [b].\nint max_int(int a, int b) { ... }\n```\n\nNote that the square bracket comment format is designed to allow\ncomments to refer to declarations using a fairly natural format\nbut does not allow *arbitrary expressions*. In particular, code\nreferences within square brackets can consist of either\n\n- a single identifier where the identifier is any identifier in scope for the comment (see the spec for what is in scope in doc comments),\n- two identifiers separated by a period where the first identifier is the name of a class that is in scope and the second is the name of a member declared in the class,\n- a single identifier followed by a pair of parentheses where the identifier is the name of a class that is in scope (used to refer to the unnamed constructor for the class), or\n- two identifiers separated by a period and followed by a pair of parentheses where the first identifier is the name of a class that is in scope and the second is the name of a named constructor (not strictly necessary, but allowed for consistency).\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.17" }, @@ -194,7 +194,7 @@ "flutter" ], "fixStatus": "needsEvaluation", - "details": "**AVOID** control flow leaving finally blocks.\n\nUsing control flow in finally blocks will inevitably cause unexpected behavior\nthat is hard to debug.\n\n**GOOD:**\n```dart\nclass Ok {\n double compliantMethod() {\n var i = 5;\n try {\n i = 1 / 0;\n } catch (e) {\n print(e); // OK\n }\n return i;\n }\n}\n```\n\n**BAD:**\n```dart\nclass BadReturn {\n double nonCompliantMethod() {\n try {\n return 1 / 0;\n } catch (e) {\n print(e);\n } finally {\n return 1.0; // LINT\n }\n }\n}\n```\n\n**BAD:**\n```dart\nclass BadContinue {\n double nonCompliantMethod() {\n for (var o in [1, 2]) {\n try {\n print(o / 0);\n } catch (e) {\n print(e);\n } finally {\n continue; // LINT\n }\n }\n return 1.0;\n }\n}\n```\n\n**BAD:**\n```dart\nclass BadBreak {\n double nonCompliantMethod() {\n for (var o in [1, 2]) {\n try {\n print(o / 0);\n } catch (e) {\n print(e);\n } finally {\n break; // LINT\n }\n }\n return 1.0;\n }\n}\n```\n\n", + "details": "**AVOID** control flow leaving finally blocks.\n\nUsing control flow in finally blocks will inevitably cause unexpected behavior\nthat is hard to debug.\n\n**BAD:**\n```dart\nclass BadReturn {\n double nonCompliantMethod() {\n try {\n return 1 / 0;\n } catch (e) {\n print(e);\n } finally {\n return 1.0; // LINT\n }\n }\n}\n```\n\n**BAD:**\n```dart\nclass BadContinue {\n double nonCompliantMethod() {\n for (var o in [1, 2]) {\n try {\n print(o / 0);\n } catch (e) {\n print(e);\n } finally {\n continue; // LINT\n }\n }\n return 1.0;\n }\n}\n```\n\n**BAD:**\n```dart\nclass BadBreak {\n double nonCompliantMethod() {\n for (var o in [1, 2]) {\n try {\n print(o / 0);\n } catch (e) {\n print(e);\n } finally {\n break; // LINT\n }\n }\n return 1.0;\n }\n}\n```\n\n**GOOD:**\n```dart\nclass Ok {\n double compliantMethod() {\n var i = 5;\n try {\n i = 1 / 0;\n } catch (e) {\n print(e); // OK\n }\n return i;\n }\n}\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.16" }, @@ -317,7 +317,7 @@ "incompatible": [], "sets": [], "fixStatus": "needsEvaluation", - "details": "**DON'T** use adjacent strings in list.\n\nThis can be sign of forgotten comma.\n\n**GOOD:**\n```dart\nList list = [\n 'a' +\n 'b',\n 'c',\n];\n```\n\n**BAD:**\n```dart\nList list = [\n 'a'\n 'b',\n 'c',\n];\n```\n\n", + "details": "**DON'T** use adjacent strings in list.\n\nThis can be sign of forgotten comma.\n\n**BAD:**\n```dart\nList list = [\n 'a'\n 'b',\n 'c',\n];\n```\n\n**GOOD:**\n```dart\nList list = [\n 'a' +\n 'b',\n 'c',\n];\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.30" }, @@ -333,7 +333,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "**DON'T** use more than one case with same value.\n\nThis is usually a typo or changed value of constant.\n\n**GOOD:**\n```dart\nconst int A = 1;\nswitch (v) {\n case A:\n case 2:\n}\n```\n\n**BAD:**\n```dart\nconst int A = 1;\nswitch (v) {\n case 1:\n case 2:\n case A:\n case 2:\n}\n```\n\n", + "details": "**DON'T** use more than one case with same value.\n\nThis is usually a typo or changed value of constant.\n\n**BAD:**\n```dart\nconst int A = 1;\nswitch (v) {\n case 1:\n case 2:\n case A:\n case 2:\n}\n```\n\n**GOOD:**\n```dart\nconst int A = 1;\nswitch (v) {\n case A:\n case 2:\n}\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.30" }, @@ -359,7 +359,7 @@ "incompatible": [], "sets": [], "fixStatus": "hasFix", - "details": "**PREFER** relative imports for files in `lib/`.\n\nWhen mixing relative and absolute imports it's possible to create confusion\nwhere the same member gets imported in two different ways. One way to avoid\nthat is to ensure you consistently use relative imports for files within the\n`lib/` directory.\n\n**GOOD:**\n\n```dart\nimport 'bar.dart';\n```\n\n**BAD:**\n\n```dart\nimport 'package:my_package/bar.dart';\n```\n\n", + "details": "**PREFER** relative imports for files in `lib/`.\n\nWhen mixing relative and absolute imports it's possible to create confusion\nwhere the same member gets imported in two different ways. One way to avoid\nthat is to ensure you consistently use relative imports for files within the\n`lib/` directory.\n\n**BAD:**\n```dart\nimport 'package:my_package/bar.dart';\n```\n\n**GOOD:**\n```dart\nimport 'bar.dart';\n```\n\n", "sinceDartSdk": "2.6.0", "sinceLinter": "0.1.99" }, @@ -386,7 +386,7 @@ "incompatible": [], "sets": [], "fixStatus": "needsEvaluation", - "details": "**DO** test type arguments in operator ==(Object other).\n\nNot testing types might result in null pointer exceptions which will be\nunexpected for consumers of your class.\n\n**GOOD:**\n```dart\nclass Field {\n}\n\nclass Good {\n final Field someField;\n\n Good(this.someField);\n\n @override\n bool operator ==(Object other) {\n if (identical(this, other)) {\n return true;\n }\n return other is Good &&\n this.someField == other.someField;\n }\n\n @override\n int get hashCode {\n return someField.hashCode;\n }\n}\n```\n\n**BAD:**\n```dart\nclass Field {\n}\n\nclass Bad {\n final Field someField;\n\n Bad(this.someField);\n\n @override\n bool operator ==(Object other) {\n Bad otherBad = other as Bad; // LINT\n bool areEqual = otherBad != null && otherBad.someField == someField;\n return areEqual;\n }\n\n @override\n int get hashCode {\n return someField.hashCode;\n }\n}\n```\n\n", + "details": "**DO** test type arguments in operator ==(Object other).\n\nNot testing types might result in null pointer exceptions which will be\nunexpected for consumers of your class.\n\n**BAD:**\n```dart\nclass Field {\n}\n\nclass Bad {\n final Field someField;\n\n Bad(this.someField);\n\n @override\n bool operator ==(Object other) {\n Bad otherBad = other as Bad; // LINT\n bool areEqual = otherBad != null && otherBad.someField == someField;\n return areEqual;\n }\n\n @override\n int get hashCode {\n return someField.hashCode;\n }\n}\n```\n\n**GOOD:**\n```dart\nclass Field {\n}\n\nclass Good {\n final Field someField;\n\n Good(this.someField);\n\n @override\n bool operator ==(Object other) {\n if (identical(this, other)) {\n return true;\n }\n return other is Good &&\n this.someField == other.someField;\n }\n\n @override\n int get hashCode {\n return someField.hashCode;\n }\n}\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.16" }, @@ -398,7 +398,7 @@ "incompatible": [], "sets": [], "fixStatus": "needsEvaluation", - "details": "**AVOID** throwing exceptions in finally blocks.\n\nThrowing exceptions in finally blocks will inevitably cause unexpected behavior\nthat is hard to debug.\n\n**GOOD:**\n```dart\nclass Ok {\n double compliantMethod() {\n var i = 5;\n try {\n i = 1 / 0;\n } catch (e) {\n print(e); // OK\n }\n return i;\n }\n}\n```\n\n**BAD:**\n```dart\nclass BadThrow {\n double nonCompliantMethod() {\n try {\n print('hello world! ${1 / 0}');\n } catch (e) {\n print(e);\n } finally {\n throw 'Find the hidden error :P'; // LINT\n }\n }\n}\n```\n\n", + "details": "**AVOID** throwing exceptions in finally blocks.\n\nThrowing exceptions in finally blocks will inevitably cause unexpected behavior\nthat is hard to debug.\n\n**BAD:**\n```dart\nclass BadThrow {\n double nonCompliantMethod() {\n try {\n print('hello world! ${1 / 0}');\n } catch (e) {\n print(e);\n } finally {\n throw 'Find the hidden error :P'; // LINT\n }\n }\n}\n```\n\n**GOOD:**\n```dart\nclass Ok {\n double compliantMethod() {\n var i = 5;\n try {\n i = 1 / 0;\n } catch (e) {\n print(e); // OK\n }\n return i;\n }\n}\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.16" }, @@ -452,7 +452,7 @@ "flutter" ], "fixStatus": "needsEvaluation", - "details": "**DON'T** use BuildContext across asynchronous gaps.\n\nStoring `BuildContext` for later usage can easily lead to difficult to diagnose\ncrashes. Asynchronous gaps are implicitly storing `BuildContext` and are some of\nthe easiest to overlook when writing code.\n\nWhen a `BuildContext` is used, its `mounted` property must be checked after an\nasynchronous gap.\n\n**GOOD:**\n```dart\nvoid onButtonTapped(BuildContext context) {\n Navigator.of(context).pop();\n}\n```\n\n**BAD:**\n```dart\nvoid onButtonTapped(BuildContext context) async {\n await Future.delayed(const Duration(seconds: 1));\n Navigator.of(context).pop();\n}\n```\n\n**GOOD:**\n```dart\nvoid onButtonTapped() async {\n await Future.delayed(const Duration(seconds: 1));\n\n if (!context.mounted) return;\n Navigator.of(context).pop();\n}\n```\n", + "details": "**DON'T** use BuildContext across asynchronous gaps.\n\nStoring `BuildContext` for later usage can easily lead to difficult to diagnose\ncrashes. Asynchronous gaps are implicitly storing `BuildContext` and are some of\nthe easiest to overlook when writing code.\n\nWhen a `BuildContext` is used, its `mounted` property must be checked after an\nasynchronous gap.\n\n**BAD:**\n```dart\nvoid onButtonTapped(BuildContext context) async {\n await Future.delayed(const Duration(seconds: 1));\n Navigator.of(context).pop();\n}\n```\n\n**GOOD:**\n```dart\nvoid onButtonTapped(BuildContext context) {\n Navigator.of(context).pop();\n}\n```\n\n**GOOD:**\n```dart\nvoid onButtonTapped() async {\n await Future.delayed(const Duration(seconds: 1));\n\n if (!context.mounted) return;\n Navigator.of(context).pop();\n}\n```\n", "sinceDartSdk": "2.13.0", "sinceLinter": "1.1.0" }, @@ -525,7 +525,7 @@ "incompatible": [], "sets": [], "fixStatus": "needsEvaluation", - "details": "**DO** Use secure urls in `pubspec.yaml`.\n\nUse `https` instead of `http` or `git:`.\n\n**GOOD:**\n```yaml\nrepository: https://github.com/dart-lang/example\n```\n\n**BAD:**\n```yaml\nrepository: http://github.com/dart-lang/example\n```\n\n```yaml\ngit:\n url: git://github.com/dart-lang/example/example.git \n```\n", + "details": "**DO** Use secure urls in `pubspec.yaml`.\n\nUse `https` instead of `http` or `git:`.\n\n**BAD:**\n```yaml\nrepository: http://github.com/dart-lang/example\n```\n\n```yaml\ngit:\n url: git://github.com/dart-lang/example/example.git\n```\n\n**GOOD:**\n```yaml\nrepository: https://github.com/dart-lang/example\n```\n\n", "sinceDartSdk": "2.16.0", "sinceLinter": "1.15.0" }, @@ -561,7 +561,7 @@ "incompatible": [], "sets": [], "fixStatus": "hasFix", - "details": "From the [flutter style guide](https://flutter.dev/style-guide/):\n\n**DO** separate the control structure expression from its statement.\n\nDon't put the statement part of an `if`, `for`, `while`, `do` on the same line\nas the expression, even if it is short. Doing so makes it unclear that there\nis relevant code there. This is especially important for early returns.\n\n**GOOD:**\n```dart\nif (notReady)\n return;\n\nif (notReady)\n return;\nelse\n print('ok')\n\nwhile (condition)\n i += 1;\n```\n\n**BAD:**\n```dart\nif (notReady) return;\n\nif (notReady)\n return;\nelse print('ok')\n\nwhile (condition) i += 1;\n```\n\n", + "details": "From the [style guide for the flutter repo](https://flutter.dev/style-guide/):\n\n**DO** separate the control structure expression from its statement.\n\nDon't put the statement part of an `if`, `for`, `while`, `do` on the same line\nas the expression, even if it is short. Doing so makes it unclear that there\nis relevant code there. This is especially important for early returns.\n\n**BAD:**\n```dart\nif (notReady) return;\n\nif (notReady)\n return;\nelse print('ok')\n\nwhile (condition) i += 1;\n```\n\n**GOOD:**\n```dart\nif (notReady)\n return;\n\nif (notReady)\n return;\nelse\n print('ok')\n\nwhile (condition)\n i += 1;\n```\n\nNote that this rule can conflict with the\n[Dart formatter](https://dart.dev/tools/dart-format), and should not be enabled\nwhen the Dart formatter is used.\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.31" }, @@ -573,7 +573,7 @@ "incompatible": [], "sets": [], "fixStatus": "needsFix", - "details": "**DO** specify `required` on named parameter before other named parameters.\n\n**GOOD:**\n```dart\nm({required a, b, c}) ;\n```\n\n**BAD:**\n```dart\nm({b, c, required a}) ;\n```\n\n**GOOD:**\n```dart\nm({@required a, b, c}) ;\n```\n\n**BAD:**\n```dart\nm({b, c, @required a}) ;\n```\n\n", + "details": "**DO** specify `required` on named parameter before other named parameters.\n\n**BAD:**\n```dart\nm({b, c, required a}) ;\n```\n\n**GOOD:**\n```dart\nm({required a, b, c}) ;\n```\n\n**BAD:**\n```dart\nm({b, c, @required a}) ;\n```\n\n**GOOD:**\n```dart\nm({@required a, b, c}) ;\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.33" }, @@ -588,7 +588,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "**DO** specify `@required` on named parameters without a default value on which \nan `assert(param != null)` is done.\n\n**GOOD:**\n```dart\nm1({@required a}) {\n assert(a != null);\n}\n\nm2({a: 1}) {\n assert(a != null);\n}\n```\n\n**BAD:**\n```dart\nm1({a}) {\n assert(a != null);\n}\n```\n\nNOTE: Only asserts at the start of the bodies will be taken into account.\n\n", + "details": "**DO** specify `@required` on named parameters without a default value on which \nan `assert(param != null)` is done.\n\n**BAD:**\n```dart\nm1({a}) {\n assert(a != null);\n}\n```\n\n**GOOD:**\n```dart\nm1({@required a}) {\n assert(a != null);\n}\n\nm2({a: 1}) {\n assert(a != null);\n}\n```\n\nNOTE: Only asserts at the start of the bodies will be taken into account.\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.31" }, @@ -603,7 +603,7 @@ ], "sets": [], "fixStatus": "hasFix", - "details": "From the [flutter style guide](https://flutter.dev/style-guide/):\n\n**DO** specify type annotations.\n\nAvoid `var` when specifying that a type is unknown and short-hands that elide\ntype annotations. Use `dynamic` if you are being explicit that the type is\nunknown. Use `Object` if you are being explicit that you want an object that\nimplements `==` and `hashCode`.\n\n**GOOD:**\n```dart\nint foo = 10;\nfinal Bar bar = Bar();\nString baz = 'hello';\nconst int quux = 20;\n```\n\n**BAD:**\n```dart\nvar foo = 10;\nfinal bar = Bar();\nconst quux = 20;\n```\n\nNOTE: Using the the `@optionalTypeArgs` annotation in the `meta` package, API\nauthors can special-case type variables whose type needs to by dynamic but whose\ndeclaration should be treated as optional. For example, suppose you have a\n`Key` object whose type parameter you'd like to treat as optional. Using the\n`@optionalTypeArgs` would look like this:\n\n```dart\nimport 'package:meta/meta.dart';\n\n@optionalTypeArgs\nclass Key {\n ...\n}\n\nmain() {\n Key s = Key(); // OK!\n}\n```\n\n", + "details": "From the [style guide for the flutter repo](https://flutter.dev/style-guide/):\n\n**DO** specify type annotations.\n\nAvoid `var` when specifying that a type is unknown and short-hands that elide\ntype annotations. Use `dynamic` if you are being explicit that the type is\nunknown. Use `Object` if you are being explicit that you want an object that\nimplements `==` and `hashCode`.\n\n**BAD:**\n```dart\nvar foo = 10;\nfinal bar = Bar();\nconst quux = 20;\n```\n\n**GOOD:**\n```dart\nint foo = 10;\nfinal Bar bar = Bar();\nString baz = 'hello';\nconst int quux = 20;\n```\n\nNOTE: Using the the `@optionalTypeArgs` annotation in the `meta` package, API\nauthors can special-case type variables whose type needs to by dynamic but whose\ndeclaration should be treated as optional. For example, suppose you have a\n`Key` object whose type parameter you'd like to treat as optional. Using the\n`@optionalTypeArgs` would look like this:\n\n```dart\nimport 'package:meta/meta.dart';\n\n@optionalTypeArgs\nclass Key {\n ...\n}\n\nmain() {\n Key s = Key(); // OK!\n}\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.4" }, @@ -618,7 +618,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "**DO** annotate overridden methods and fields.\n\nThis practice improves code readability and helps protect against\nunintentionally overriding superclass members.\n\n**GOOD:**\n```dart\nabstract class Dog {\n String get breed;\n void bark() {}\n}\n\nclass Husky extends Dog {\n @override\n final String breed = 'Husky';\n @override\n void bark() {}\n}\n```\n\n**BAD:**\n```dart\nclass Cat {\n int get lives => 9;\n}\n\nclass Lucky extends Cat {\n final int lives = 14;\n}\n```\n\n", + "details": "**DO** annotate overridden methods and fields.\n\nThis practice improves code readability and helps protect against\nunintentionally overriding superclass members.\n\n**BAD:**\n```dart\nclass Cat {\n int get lives => 9;\n}\n\nclass Lucky extends Cat {\n final int lives = 14;\n}\n```\n\n**GOOD:**\n```dart\nabstract class Dog {\n String get breed;\n void bark() {}\n}\n\nclass Husky extends Dog {\n @override\n final String breed = 'Husky';\n @override\n void bark() {}\n}\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.11" }, @@ -642,7 +642,7 @@ "incompatible": [], "sets": [], "fixStatus": "noFix", - "details": "**AVOID** using `as`.\n\nIf you know the type is correct, use an assertion or assign to a more\nnarrowly-typed variable (this avoids the type check in release mode; `as` is not\ncompiled out in release mode). If you don't know whether the type is\ncorrect, check using `is` (this avoids the exception that `as` raises).\n\n**BAD:**\n```dart\n(pm as Person).firstName = 'Seth';\n```\n\n**GOOD:**\n```dart\nif (pm is Person)\n pm.firstName = 'Seth';\n```\n\nbut certainly not\n\n**BAD:**\n```dart\ntry {\n (pm as Person).firstName = 'Seth';\n} on CastError { }\n```\n\nNote that an exception is made in the case of `dynamic` since the cast has no\nperformance impact.\n\n**OK:**\n```dart\nHasScrollDirection scrollable = renderObject as dynamic;\n```\n\n\n**DEPRECATED:** This advice is no longer recommended.\n \nThe rule will be removed in a future Linter release.\n", + "details": "**AVOID** using `as`.\n\nIf you know the type is correct, use an assertion or assign to a more\nnarrowly-typed variable (this avoids the type check in release mode; `as` is not\ncompiled out in release mode). If you don't know whether the type is\ncorrect, check using `is` (this avoids the exception that `as` raises).\n\n**BAD:**\n```dart\n(pm as Person).firstName = 'Seth';\n```\n\n**GOOD:**\n```dart\nif (pm is Person)\n pm.firstName = 'Seth';\n```\n\nbut certainly not\n\n**BAD:**\n```dart\ntry {\n (pm as Person).firstName = 'Seth';\n} on CastError { }\n```\n\nNote that an exception is made in the case of `dynamic` since the cast has no\nperformance impact.\n\n**OK:**\n```dart\nHasScrollDirection scrollable = renderObject as dynamic;\n```\n\n\n**DEPRECATED:** This advice is no longer recommended.\n\nThe rule will be removed in a future Linter release.\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.5" }, @@ -690,7 +690,7 @@ "incompatible": [], "sets": [], "fixStatus": "needsEvaluation", - "details": "**AVOID** defining a class that contains only static members.\n\nCreating classes with the sole purpose of providing utility or otherwise static\nmethods is discouraged. Dart allows functions to exist outside of classes for\nthis very reason.\n\n**BAD:**\n```dart\nclass DateUtils {\n static DateTime mostRecent(List dates) {\n return dates.reduce((a, b) => a.isAfter(b) ? a : b);\n }\n}\n\nclass _Favorites {\n static const mammal = 'weasel';\n}\n```\n\n**GOOD:**\n```dart\nDateTime mostRecent(List dates) {\n return dates.reduce((a, b) => a.isAfter(b) ? a : b);\n}\n\nconst _favoriteMammal = 'weasel';\n```\n\n", + "details": "From [Effective Dart](https://dart.dev/guides/language/effective-dart/design#avoid-defining-a-class-that-contains-only-static-members):\n\n**AVOID** defining a class that contains only static members.\n\nCreating classes with the sole purpose of providing utility or otherwise static\nmethods is discouraged. Dart allows functions to exist outside of classes for\nthis very reason.\n\n**BAD:**\n```dart\nclass DateUtils {\n static DateTime mostRecent(List dates) {\n return dates.reduce((a, b) => a.isAfter(b) ? a : b);\n }\n}\n\nclass _Favorites {\n static const mammal = 'weasel';\n}\n```\n\n**GOOD:**\n```dart\nDateTime mostRecent(List dates) {\n return dates.reduce((a, b) => a.isAfter(b) ? a : b);\n}\n\nconst _favoriteMammal = 'weasel';\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.31" }, @@ -714,7 +714,7 @@ "incompatible": [], "sets": [], "fixStatus": "needsEvaluation", - "details": "**AVOID** overloading operator == and hashCode on classes not marked `@immutable`.\n\nIf a class is not immutable, overloading operator == and hashCode can lead to\nunpredictable and undesirable behavior when used in collections. See\nhttps://dart.dev/guides/language/effective-dart/design#avoid-defining-custom-equality-for-mutable-classes\nfor more information.\n\n**GOOD:**\n```dart\n@immutable\nclass A {\n final String key;\n const A(this.key);\n @override\n operator ==(other) => other is A && other.key == key;\n @override\n int get hashCode => key.hashCode;\n}\n```\n\n**BAD:**\n```dart\nclass B {\n String key;\n const B(this.key);\n @override\n operator ==(other) => other is B && other.key == key;\n @override\n int get hashCode => key.hashCode;\n}\n```\n\nNOTE: The lint checks the use of the @immutable annotation, and will trigger\neven if the class is otherwise not mutable. Thus:\n\n**BAD:**\n```dart\nclass C {\n final String key;\n const C(this.key);\n @override\n operator ==(other) => other is C && other.key == key;\n @override\n int get hashCode => key.hashCode;\n}\n```\n\n", + "details": "**AVOID** overloading operator == and hashCode on classes not marked `@immutable`.\n\nIf a class is not immutable, overloading operator == and hashCode can lead to\nunpredictable and undesirable behavior when used in collections. See\nhttps://dart.dev/guides/language/effective-dart/design#avoid-defining-custom-equality-for-mutable-classes\nfor more information.\n\n**BAD:**\n```dart\nclass B {\n String key;\n const B(this.key);\n @override\n operator ==(other) => other is B && other.key == key;\n @override\n int get hashCode => key.hashCode;\n}\n```\n\n**GOOD:**\n```dart\n@immutable\nclass A {\n final String key;\n const A(this.key);\n @override\n operator ==(other) => other is A && other.key == key;\n @override\n int get hashCode => key.hashCode;\n}\n```\n\nNOTE: The lint checks the use of the `@immutable` annotation, and will trigger\neven if the class is otherwise not mutable. Thus:\n\n**BAD:**\n```dart\nclass C {\n final String key;\n const C(this.key);\n @override\n operator ==(other) => other is C && other.key == key;\n @override\n int get hashCode => key.hashCode;\n}\n```\n\n", "sinceDartSdk": "2.6.0", "sinceLinter": "0.1.97" }, @@ -752,7 +752,7 @@ ], "sets": [], "fixStatus": "needsEvaluation", - "details": "**AVOID** declaring parameters as final.\n\nDeclaring parameters as final can lead to unnecessarily verbose code, especially\nwhen using the \"parameter_assignments\" rule.\n\n**GOOD:**\n```dart\nvoid badParameter(String label) { // OK\n print(label);\n}\n```\n\n**BAD:**\n```dart\nvoid goodParameter(final String label) { // LINT\n print(label);\n}\n```\n\n**GOOD:**\n```dart\nvoid badExpression(int value) => print(value); // OK\n```\n\n**BAD:**\n```dart\nvoid goodExpression(final int value) => print(value); // LINT\n```\n\n**GOOD:**\n```dart\n[1, 4, 6, 8].forEach((value) => print(value + 2)); // OK\n```\n\n**BAD:**\n```dart\n[1, 4, 6, 8].forEach((final value) => print(value + 2)); // LINT\n```\n\n", + "details": "**AVOID** declaring parameters as final.\n\nDeclaring parameters as final can lead to unnecessarily verbose code, especially\nwhen using the \"parameter_assignments\" rule.\n\n**BAD:**\n```dart\nvoid goodParameter(final String label) { // LINT\n print(label);\n}\n```\n\n**GOOD:**\n```dart\nvoid badParameter(String label) { // OK\n print(label);\n}\n```\n\n**BAD:**\n```dart\nvoid goodExpression(final int value) => print(value); // LINT\n```\n\n**GOOD:**\n```dart\nvoid badExpression(int value) => print(value); // OK\n```\n\n**BAD:**\n```dart\n[1, 4, 6, 8].forEach((final value) => print(value + 2)); // LINT\n```\n\n**GOOD:**\n```dart\n[1, 4, 6, 8].forEach((value) => print(value + 2)); // OK\n```\n\n", "sinceDartSdk": "2.16.0", "sinceLinter": "1.15.0" }, @@ -767,7 +767,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "**AVOID** using `forEach` with a function literal.\n\nThe `for` loop enables a developer to be clear and explicit as to their intent.\nA return in the body of the `for` loop returns from the body of the function, \nwhere as a return in the body of the `forEach` closure only returns a value \nfor that iteration of the `forEach`. The body of a `for` loop can contain \n`await`s, while the closure body of a `forEach` cannot.\n\n**BAD:**\n```dart\npeople.forEach((person) {\n ...\n});\n```\n\n**GOOD:**\n```dart\nfor (var person in people) {\n ...\n}\n```\n", + "details": "**AVOID** using `forEach` with a function literal.\n\nThe `for` loop enables a developer to be clear and explicit as to their intent.\nA return in the body of the `for` loop returns from the body of the function,\nwhere as a return in the body of the `forEach` closure only returns a value\nfor that iteration of the `forEach`. The body of a `for` loop can contain\n`await`s, while the closure body of a `forEach` cannot.\n\n**BAD:**\n```dart\npeople.forEach((person) {\n ...\n});\n```\n\n**GOOD:**\n```dart\nfor (var person in people) {\n ...\n}\n```\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.30" }, @@ -779,7 +779,7 @@ "incompatible": [], "sets": [], "fixStatus": "needsEvaluation", - "details": "**DON'T** implement classes that override `==`.\n\nThe `==` operator is contractually required to be an equivalence relation;\nthat is, symmetrically for all objects `o1` and `o2`, `o1 == o2` and `o2 == o1`\nmust either both be true, or both be false.\n\n> _NOTE_: Dart does not have true _value types_, so instead we consider a class\n> that implements `==` as a _proxy_ for identifying value types.\n\nWhen using `implements`, you do not inherit the method body of `==`, making it\nnearly impossible to follow the contract of `==`. Classes that override `==`\ntypically are usable directly in tests _without_ creating mocks or fakes as\nwell. For example, for a given class `Size`:\n\n```dart\nclass Size {\n final int inBytes;\n const Size(this.inBytes);\n\n @override\n bool operator ==(Object other) => other is Size && other.inBytes == inBytes;\n\n @override\n int get hashCode => inBytes.hashCode;\n}\n```\n\n**BAD**:\n```dart\nclass CustomSize implements Size {\n final int inBytes;\n const CustomSize(this.inBytes);\n\n int get inKilobytes => inBytes ~/ 1000;\n}\n```\n\n**BAD**:\n```dart\nimport 'package:test/test.dart';\nimport 'size.dart';\n\nclass FakeSize implements Size {\n int inBytes = 0;\n}\n\nvoid main() {\n test('should not throw on a size >1Kb', () {\n expect(() => someFunction(FakeSize()..inBytes = 1001), returnsNormally);\n });\n}\n```\n\n**GOOD**:\n```dart\nclass ExtendedSize extends Size {\n ExtendedSize(int inBytes) : super(inBytes);\n\n int get inKilobytes => inBytes ~/ 1000;\n}\n```\n\n**GOOD**:\n```dart\nimport 'package:test/test.dart';\nimport 'size.dart';\n\nvoid main() {\n test('should not throw on a size >1Kb', () {\n expect(() => someFunction(Size(1001)), returnsNormally);\n });\n}\n```\n\n", + "details": "**DON'T** implement classes that override `==`.\n\nThe `==` operator is contractually required to be an equivalence relation;\nthat is, symmetrically for all objects `o1` and `o2`, `o1 == o2` and `o2 == o1`\nmust either both be true, or both be false.\n\n> _NOTE_: Dart does not have true _value types_, so instead we consider a class\n> that implements `==` as a _proxy_ for identifying value types.\n\nWhen using `implements`, you do not inherit the method body of `==`, making it\nnearly impossible to follow the contract of `==`. Classes that override `==`\ntypically are usable directly in tests _without_ creating mocks or fakes as\nwell. For example, for a given class `Size`:\n\n```dart\nclass Size {\n final int inBytes;\n const Size(this.inBytes);\n\n @override\n bool operator ==(Object other) => other is Size && other.inBytes == inBytes;\n\n @override\n int get hashCode => inBytes.hashCode;\n}\n```\n\n**BAD:**\n```dart\nclass CustomSize implements Size {\n final int inBytes;\n const CustomSize(this.inBytes);\n\n int get inKilobytes => inBytes ~/ 1000;\n}\n```\n\n**BAD:**\n```dart\nimport 'package:test/test.dart';\nimport 'size.dart';\n\nclass FakeSize implements Size {\n int inBytes = 0;\n}\n\nvoid main() {\n test('should not throw on a size >1Kb', () {\n expect(() => someFunction(FakeSize()..inBytes = 1001), returnsNormally);\n });\n}\n```\n\n**GOOD:**\n```dart\nclass ExtendedSize extends Size {\n ExtendedSize(int inBytes) : super(inBytes);\n\n int get inKilobytes => inBytes ~/ 1000;\n}\n```\n\n**GOOD:**:\n```dart\nimport 'package:test/test.dart';\nimport 'size.dart';\n\nvoid main() {\n test('should not throw on a size >1Kb', () {\n expect(() => someFunction(Size(1001)), returnsNormally);\n });\n}\n```\n\n", "sinceDartSdk": "2.1.0", "sinceLinter": "0.1.62" }, @@ -794,7 +794,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "From [Effective Dart](https://dart.dev/guides/language/effective-dart/usage#dont-explicitly-initialize-variables-to-null):\n\n**DON'T** explicitly initialize variables to null.\n\nIn Dart, a variable or field that is not explicitly initialized automatically\ngets initialized to null. This is reliably specified by the language. There's\nno concept of \"uninitialized memory\" in Dart. Adding `= null` is redundant and\nunneeded.\n\n**GOOD:**\n```dart\nint _nextId;\n\nclass LazyId {\n int _id;\n\n int get id {\n if (_nextId == null) _nextId = 0;\n if (_id == null) _id = _nextId++;\n\n return _id;\n }\n}\n```\n\n**BAD:**\n```dart\nint _nextId = null;\n\nclass LazyId {\n int _id = null;\n\n int get id {\n if (_nextId == null) _nextId = 0;\n if (_id == null) _id = _nextId++;\n\n return _id;\n }\n}\n```\n\n", + "details": "From [Effective Dart](https://dart.dev/guides/language/effective-dart/usage#dont-explicitly-initialize-variables-to-null):\n\n**DON'T** explicitly initialize variables to null.\n\nIn Dart, a variable or field that is not explicitly initialized automatically\ngets initialized to null. This is reliably specified by the language. There's\nno concept of \"uninitialized memory\" in Dart. Adding `= null` is redundant and\nunneeded.\n\n**BAD:**\n```dart\nint _nextId = null;\n\nclass LazyId {\n int _id = null;\n\n int get id {\n if (_nextId == null) _nextId = 0;\n if (_id == null) _id = _nextId++;\n\n return _id;\n }\n}\n```\n\n**GOOD:**\n```dart\nint _nextId;\n\nclass LazyId {\n int _id;\n\n int get id {\n if (_nextId == null) _nextId = 0;\n if (_id == null) _id = _nextId++;\n\n return _id;\n }\n}\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.11" }, @@ -869,7 +869,7 @@ "incompatible": [], "sets": [], "fixStatus": "hasFix", - "details": "**DON'T** declare arguments with values that match the defaults for the\ncorresponding parameter.\n\n**BAD:**\n```dart\nvoid f({bool valWithDefault = true, bool? val}) {\n ...\n}\n\nvoid main() {\n f(valWithDefault: true);\n}\n```\n\n**GOOD:**\n```dart\nvoid f({bool valWithDefault = true, bool? val}) {\n ...\n}\n\nvoid main() {\n f(valWithDefault: false);\n f();\n}\n```\n", + "details": "**DON'T** pass an argument that matches the corresponding parameter's default\nvalue.\n\n**BAD:**\n```dart\nvoid f({bool valWithDefault = true, bool? val}) {\n ...\n}\n\nvoid main() {\n f(valWithDefault: true);\n}\n```\n\n**GOOD:**\n```dart\nvoid f({bool valWithDefault = true, bool? val}) {\n ...\n}\n\nvoid main() {\n f(valWithDefault: false);\n f();\n}\n```\n", "sinceDartSdk": "2.8.1", "sinceLinter": "0.1.107" }, @@ -899,7 +899,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "**AVOID** return types on setters.\n\nAs setters do not return a value, declaring the return type of one is redundant.\n\n**GOOD:**\n```dart\nset speed(int ms);\n```\n\n**BAD:**\n```dart\nvoid set speed(int ms);\n```\n\n", + "details": "**AVOID** return types on setters.\n\nAs setters do not return a value, declaring the return type of one is redundant.\n\n**BAD:**\n```dart\nvoid set speed(int ms);\n```\n\n**GOOD:**\n```dart\nset speed(int ms);\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.11" }, @@ -1033,7 +1033,7 @@ "incompatible": [], "sets": [], "fixStatus": "hasFix", - "details": "**DO** mark async functions as returning Future.\n\nWhen declaring an async method or function which does not return a value,\ndeclare that it returns `Future` and not just `void`.\n\n**BAD:**\n```dart\nvoid f() async {}\nvoid f2() async => null;\n```\n\n**GOOD:**\n```dart\nFuture f() async {}\nFuture f2() async => null;\n```\n\n**EXCEPTION**\n\nAn exception is made for top-level `main` functions, where the `Future`\nannotation *can* (and generally should) be dropped in favor of `void`.\n\n**GOOD:**\n```dart\nFuture f() async {}\n\nvoid main() async {\n await f();\n}\n```\n", + "details": "**DO** mark async functions as returning Future.\n\nWhen declaring an async method or function which does not return a value,\ndeclare that it returns `Future` and not just `void`.\n\n**BAD:**\n```dart\nvoid f() async {}\nvoid f2() async => null;\n```\n\n**GOOD:**\n```dart\nFuture f() async {}\nFuture f2() async => null;\n```\n\n**EXCEPTION:**\n\nAn exception is made for top-level `main` functions, where the `Future`\nannotation *can* (and generally should) be dropped in favor of `void`.\n\n**GOOD:**\n```dart\nFuture f() async {}\n\nvoid main() async {\n await f();\n}\n```\n", "sinceDartSdk": "2.1.0", "sinceLinter": "0.1.60" }, @@ -1144,7 +1144,7 @@ "flutter" ], "fixStatus": "needsEvaluation", - "details": "**PREFER** using lowerCamelCase for constant names.\n\nIn new code, use `lowerCamelCase` for constant variables, including enum values.\n\nIn existing code that uses `ALL_CAPS_WITH_UNDERSCORES` for constants, you may\ncontinue to use all caps to stay consistent.\n\n**GOOD:**\n```dart\nconst pi = 3.14;\nconst defaultTimeout = 1000;\nfinal urlScheme = RegExp('^([a-z]+):');\n\nclass Dice {\n static final numberGenerator = Random();\n}\n```\n\n**BAD:**\n```dart\nconst PI = 3.14;\nconst kDefaultTimeout = 1000;\nfinal URL_SCHEME = RegExp('^([a-z]+):');\n\nclass Dice {\n static final NUMBER_GENERATOR = Random();\n}\n\n```\n\n", + "details": "**PREFER** using lowerCamelCase for constant names.\n\nIn new code, use `lowerCamelCase` for constant variables, including enum values.\n\nIn existing code that uses `ALL_CAPS_WITH_UNDERSCORES` for constants, you may\ncontinue to use all caps to stay consistent.\n\n**BAD:**\n```dart\nconst PI = 3.14;\nconst kDefaultTimeout = 1000;\nfinal URL_SCHEME = RegExp('^([a-z]+):');\n\nclass Dice {\n static final NUMBER_GENERATOR = Random();\n}\n```\n\n**GOOD:**\n```dart\nconst pi = 3.14;\nconst defaultTimeout = 1000;\nfinal urlScheme = RegExp('^([a-z]+):');\n\nclass Dice {\n static final numberGenerator = Random();\n}\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.1" }, @@ -1160,7 +1160,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "**DO** use curly braces for all flow control structures.\n\nDoing so avoids the [dangling else](https://en.wikipedia.org/wiki/Dangling_else)\nproblem.\n\n**GOOD:**\n```dart\nif (isWeekDay) {\n print('Bike to work!');\n} else {\n print('Go dancing or read a book!');\n}\n```\n\nThere is one exception to this: an `if` statement with no `else` clause where\nthe entire `if` statement and the then body all fit in one line. In that case,\nyou may leave off the braces if you prefer:\n\n**GOOD:**\n```dart\nif (arg == null) return defaultValue;\n```\n\nIf the body wraps to the next line, though, use braces:\n\n**GOOD:**\n```dart\nif (overflowChars != other.overflowChars) {\n return overflowChars < other.overflowChars;\n}\n```\n\n**BAD:**\n```dart\nif (overflowChars != other.overflowChars)\n return overflowChars < other.overflowChars;\n```\n", + "details": "**DO** use curly braces for all flow control structures.\n\nDoing so avoids the [dangling else](https://en.wikipedia.org/wiki/Dangling_else)\nproblem.\n\n**BAD:**\n```dart\nif (overflowChars != other.overflowChars)\n return overflowChars < other.overflowChars;\n```\n\n**GOOD:**\n```dart\nif (isWeekDay) {\n print('Bike to work!');\n} else {\n print('Go dancing or read a book!');\n}\n```\n\nThere is one exception to this: an `if` statement with no `else` clause where\nthe entire `if` statement and the then body all fit in one line. In that case,\nyou may leave off the braces if you prefer:\n\n**GOOD:**\n```dart\nif (arg == null) return defaultValue;\n```\n\nIf the body wraps to the next line, though, use braces:\n\n**GOOD:**\n```dart\nif (overflowChars != other.overflowChars) {\n return overflowChars < other.overflowChars;\n}\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.57" }, @@ -1239,7 +1239,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "From the [style guide](https://dart.dev/guides/language/effective-dart/style/):\n\n**DO** use `;` instead of `{}` for empty constructor bodies.\n\nIn Dart, a constructor with an empty body can be terminated with just a\nsemicolon. This is required for const constructors. For consistency and\nbrevity, other constructors should also do this.\n\n**GOOD:**\n```dart\nclass Point {\n int x, y;\n Point(this.x, this.y);\n}\n```\n\n**BAD:**\n```dart\nclass Point {\n int x, y;\n Point(this.x, this.y) {}\n}\n```\n\n", + "details": "From the [style guide](https://dart.dev/guides/language/effective-dart/style/):\n\n**DO** use `;` instead of `{}` for empty constructor bodies.\n\nIn Dart, a constructor with an empty body can be terminated with just a\nsemicolon. This is required for const constructors. For consistency and\nbrevity, other constructors should also do this.\n\n**BAD:**\n```dart\nclass Point {\n int x, y;\n Point(this.x, this.y) {}\n}\n```\n\n**GOOD:**\n```dart\nclass Point {\n int x, y;\n Point(this.x, this.y);\n}\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.1" }, @@ -1250,10 +1250,10 @@ "maturity": "stable", "incompatible": [], "sets": [], - "fixStatus": "unregistered", - "details": "**DO** use sound null safety, by not specifying a dart version lower than `2.12`.\n\n**BAD:**\n```dart\n// @dart=2.8\na() {\n}\n```\n\n**GOOD:**\n```dart\nb() {\n}\n", + "fixStatus": "noFix", + "details": "**DO** use sound null safety, by not specifying a dart version lower than `2.12`.\n\n**BAD:**\n```dart\n// @dart=2.8\na() {\n}\n```\n\n**GOOD:**\n```dart\nb() {\n}\n```\n", "sinceDartSdk": "Unreleased", - "sinceLinter": "Unreleased" + "sinceLinter": "1.30.0" }, { "name": "eol_at_end_of_file", @@ -1294,7 +1294,7 @@ "flutter" ], "fixStatus": "needsEvaluation", - "details": "**DO** name source files using `lowercase_with_underscores`.\n\nSome file systems are not case-sensitive, so many projects require filenames to\nbe all lowercase. Using a separating character allows names to still be readable\nin that form. Using underscores as the separator ensures that the name is still\na valid Dart identifier, which may be helpful if the language later supports\nsymbolic imports.\n\n**GOOD:**\n\n* `slider_menu.dart`\n* `file_system.dart`\n\n**BAD:**\n\n* `SliderMenu.dart`\n* `filesystem.dart`\n* `file-system.dart`\n\nFiles without a strict `.dart` extension are ignored. For example:\n\n**OK:**\n\n* `file-system.g.dart`\n* `SliderMenu.css.dart`\n\nThe lint `library_names` can be used to enforce the same kind of naming on the\nlibrary.\n\n", + "details": "**DO** name source files using `lowercase_with_underscores`.\n\nSome file systems are not case-sensitive, so many projects require filenames to\nbe all lowercase. Using a separating character allows names to still be readable\nin that form. Using underscores as the separator ensures that the name is still\na valid Dart identifier, which may be helpful if the language later supports\nsymbolic imports.\n\n**BAD:**\n\n* `SliderMenu.dart`\n* `filesystem.dart`\n* `file-system.dart`\n\n**GOOD:**\n\n* `slider_menu.dart`\n* `file_system.dart`\n\nFiles without a strict `.dart` extension are ignored. For example:\n\n**OK:**\n\n* `file-system.g.dart`\n* `SliderMenu.css.dart`\n\nThe lint `library_names` can be used to enforce the same kind of naming on the\nlibrary.\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.54" }, @@ -1321,7 +1321,7 @@ "flutter" ], "fixStatus": "needsEvaluation", - "details": "From the the [pub package layout doc](https://dart.dev/tools/pub/package-layout#implementation-files):\n\n**DON'T** import implementation files from another package.\n\nThe libraries inside `lib` are publicly visible: other packages are free to\nimport them. But much of a package's code is internal implementation libraries\nthat should only be imported and used by the package itself. Those go inside a\nsubdirectory of `lib` called `src`. You can create subdirectories in there if\nit helps you organize things.\n\nYou are free to import libraries that live in `lib/src` from within other Dart\ncode in the same package (like other libraries in `lib`, scripts in `bin`,\nand tests) but you should never import from another package's `lib/src`\ndirectory. Those files are not part of the package's public API, and they\nmight change in ways that could break your code.\n\n**BAD:**\n```dart\n// In 'road_runner'\nimport 'package:acme/lib/src/internals.dart;\n```\n\n", + "details": "From the the [pub package layout doc](https://dart.dev/tools/pub/package-layout#implementation-files):\n\n**DON'T** import implementation files from another package.\n\nThe libraries inside `lib` are publicly visible: other packages are free to\nimport them. But much of a package's code is internal implementation libraries\nthat should only be imported and used by the package itself. Those go inside a\nsubdirectory of `lib` called `src`. You can create subdirectories in there if\nit helps you organize things.\n\nYou are free to import libraries that live in `lib/src` from within other Dart\ncode in the same package (like other libraries in `lib`, scripts in `bin`,\nand tests) but you should never import from another package's `lib/src`\ndirectory. Those files are not part of the package's public API, and they\nmight change in ways that could break your code.\n\n**BAD:**\n```dart\n// In 'road_runner'\nimport 'package:acme/src/internals.dart';\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.4" }, @@ -1368,10 +1368,10 @@ "maturity": "stable", "incompatible": [], "sets": [], - "fixStatus": "unregistered", + "fixStatus": "needsFix", "details": "Attach library annotations to library directives, rather than\nsome other library-level element.\n\n**BAD:**\n```dart\nimport 'package:test/test.dart';\n\n@TestOn('browser')\nvoid main() {}\n```\n\n**GOOD:**\n```dart\n@TestOn('browser')\nlibrary;\nimport 'package:test/test.dart';\n\nvoid main() {}\n```\n\n**NOTE:** An unnamed library, like `library;` above, is only supported in Dart\n2.19 and later. Code which might run in earlier versions of Dart will need to\nprovide a name in the `library` directive.\n", "sinceDartSdk": "Unreleased", - "sinceLinter": "Unreleased" + "sinceLinter": "1.30.0" }, { "name": "library_names", @@ -1384,7 +1384,7 @@ "flutter" ], "fixStatus": "needsEvaluation", - "details": "**DO** name libraries using `lowercase_with_underscores`.\n\nSome file systems are not case-sensitive, so many projects require filenames to\nbe all lowercase. Using a separating character allows names to still be readable\nin that form. Using underscores as the separator ensures that the name is still\na valid Dart identifier, which may be helpful if the language later supports\nsymbolic imports.\n\n**GOOD:**\n```dart\nlibrary peg_parser;\n```\n\n**BAD:**\n```dart\nlibrary peg-parser;\n```\n\nThe lint `file_names` can be used to enforce the same kind of naming on the\nfile.\n\n", + "details": "**DO** name libraries using `lowercase_with_underscores`.\n\nSome file systems are not case-sensitive, so many projects require filenames to\nbe all lowercase. Using a separating character allows names to still be readable\nin that form. Using underscores as the separator ensures that the name is still\na valid Dart identifier, which may be helpful if the language later supports\nsymbolic imports.\n\n**BAD:**\n```dart\nlibrary peg-parser;\n```\n\n**GOOD:**\n```dart\nlibrary peg_parser;\n```\n\nThe lint `file_names` can be used to enforce the same kind of naming on the\nfile.\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.1" }, @@ -1399,7 +1399,7 @@ "flutter" ], "fixStatus": "needsEvaluation", - "details": "**DO** use `lowercase_with_underscores` when specifying a library prefix.\n\n**GOOD:**\n```dart\nimport 'dart:math' as math;\nimport 'dart:json' as json;\nimport 'package:js/js.dart' as js;\nimport 'package:javascript_utils/javascript_utils.dart' as js_utils;\n```\n\n**BAD:**\n```dart\nimport 'dart:math' as Math;\nimport 'dart:json' as JSON;\nimport 'package:js/js.dart' as JS;\nimport 'package:javascript_utils/javascript_utils.dart' as jsUtils;\n```\n\n", + "details": "**DO** use `lowercase_with_underscores` when specifying a library prefix.\n\n**BAD:**\n```dart\nimport 'dart:math' as Math;\nimport 'dart:json' as JSON;\nimport 'package:js/js.dart' as JS;\nimport 'package:javascript_utils/javascript_utils.dart' as jsUtils;\n```\n\n**GOOD:**\n```dart\nimport 'dart:math' as math;\nimport 'dart:json' as json;\nimport 'package:js/js.dart' as js;\nimport 'package:javascript_utils/javascript_utils.dart' as js_utils;\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.1" }, @@ -1414,7 +1414,7 @@ "flutter" ], "fixStatus": "needsEvaluation", - "details": "**AVOID** using library private types in public APIs.\n\nFor the purposes of this lint, a public API is considered to be any top-level or\nmember declaration unless the declaration is library private or contained in a\ndeclaration that's library private. The following uses of types are checked:\n\n- the return type of a function or method,\n- the type of any parameter of a function or method,\n- the bound of a type parameter to any function, method, class, mixin,\n extension's extended type, or type alias,\n- the type of any top level variable or field,\n- any type used in the declaration of a type alias (for example\n `typedef F = _Private Function();`), or\n- any type used in the `on` clause of an extension or a mixin\n\n**GOOD:**\n```dart\nf(String s) { ... }\n```\n\n**BAD:**\n```dart\nf(_Private p) { ... }\nclass _Private {}\n```\n\n", + "details": "**AVOID** using library private types in public APIs.\n\nFor the purposes of this lint, a public API is considered to be any top-level or\nmember declaration unless the declaration is library private or contained in a\ndeclaration that's library private. The following uses of types are checked:\n\n- the return type of a function or method,\n- the type of any parameter of a function or method,\n- the bound of a type parameter to any function, method, class, mixin,\n extension's extended type, or type alias,\n- the type of any top level variable or field,\n- any type used in the declaration of a type alias (for example\n `typedef F = _Private Function();`), or\n- any type used in the `on` clause of an extension or a mixin\n\n**BAD:**\n```dart\nf(_Private p) { ... }\nclass _Private {}\n```\n\n**GOOD:**\n```dart\nf(String s) { ... }\n```\n\n", "sinceDartSdk": "2.14.0", "sinceLinter": "1.3.0" }, @@ -1450,7 +1450,7 @@ "incompatible": [], "sets": [], "fixStatus": "needsEvaluation", - "details": "Switches on enums and enum-like classes should not use a `default` clause.\n\nEnum-like classes are defined as concrete (non-abstract) classes that have:\n * only private non-factory constructors\n * two or more static const fields whose type is the enclosing class and\n * no subclasses of the class in the defining library\n\n**DO** define default behavior outside switch statements.\n\n**GOOD:**\n```dart\n switch (testEnum) {\n case TestEnum.A:\n return '123';\n case TestEnum.B:\n return 'abc';\n }\n // Default here.\n return null;\n```\n\n**BAD:**\n```dart\n switch (testEnum) {\n case TestEnum.A:\n return '123';\n case TestEnum.B:\n return 'abc';\n default:\n return null;\n }\n```\n", + "details": "Switches on enums and enum-like classes should not use a `default` clause.\n\nEnum-like classes are defined as concrete (non-abstract) classes that have:\n * only private non-factory constructors\n * two or more static const fields whose type is the enclosing class and\n * no subclasses of the class in the defining library\n\n**DO** define default behavior outside switch statements.\n\n**BAD:**\n```dart\n switch (testEnum) {\n case TestEnum.A:\n return '123';\n case TestEnum.B:\n return 'abc';\n default:\n return null;\n }\n```\n\n**GOOD:**\n```dart\n switch (testEnum) {\n case TestEnum.A:\n return '123';\n case TestEnum.B:\n return 'abc';\n }\n // Default here.\n return null;\n```\n\n", "sinceDartSdk": "2.9.0", "sinceLinter": "0.1.116" }, @@ -1465,7 +1465,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "**DON'T** use a leading underscore for library prefixes.\nThere is no concept of \"private\" for library prefixes. When one of those has a\nname that starts with an underscore, it sends a confusing signal to the reader. \nTo avoid that, don't use leading underscores in those names.\n\n**BAD**\n```dart\nimport 'dart:core' as _core;\n```\n\n**GOOD:**\n```dart\nimport 'dart:core' as core;\n```\n", + "details": "**DON'T** use a leading underscore for library prefixes.\nThere is no concept of \"private\" for library prefixes. When one of those has a\nname that starts with an underscore, it sends a confusing signal to the reader. \nTo avoid that, don't use leading underscores in those names.\n\n**BAD:**\n```dart\nimport 'dart:core' as _core;\n```\n\n**GOOD:**\n```dart\nimport 'dart:core' as core;\n```\n", "sinceDartSdk": "2.16.0", "sinceLinter": "1.15.0" }, @@ -1480,7 +1480,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "**DON'T** use a leading underscore for identifiers that aren't private. Dart\nuses a leading underscore in an identifier to mark members and top-level\ndeclarations as private. This trains users to associate a leading underscore\nwith one of those kinds of declarations. They see `_` and think \"private\".\nThere is no concept of \"private\" for local variables or parameters. When one of \nthose has a name that starts with an underscore, it sends a confusing signal to\nthe reader. To avoid that, don't use leading underscores in those names.\n\n**Exception**: An unused parameter can be named `_`, `__`, `___`, etc. This is\ncommon practice in callbacks where you are passed a value but you don't need\nto use it. Giving it a name that consists solely of underscores is the idiomatic\nway to indicate that the value isn't used.\n\n**BAD**\n```dart\nvoid print(String _name) {\n var _size = _name.length;\n ...\n}\n```\n**GOOD:**\n\n```dart\nvoid print(String name) {\n var size = name.length;\n ...\n}\n```\n\n**OK:**\n\n```dart\n[1,2,3].map((_) => print('Hello'));\n```\n", + "details": "**DON'T** use a leading underscore for identifiers that aren't private. Dart\nuses a leading underscore in an identifier to mark members and top-level\ndeclarations as private. This trains users to associate a leading underscore\nwith one of those kinds of declarations. They see `_` and think \"private\".\nThere is no concept of \"private\" for local variables or parameters. When one of \nthose has a name that starts with an underscore, it sends a confusing signal to\nthe reader. To avoid that, don't use leading underscores in those names.\n\n**EXCEPTION:**: An unused parameter can be named `_`, `__`, `___`, etc. This is\ncommon practice in callbacks where you are passed a value but you don't need\nto use it. Giving it a name that consists solely of underscores is the idiomatic\nway to indicate that the value isn't used.\n\n**BAD:**\n```dart\nvoid print(String _name) {\n var _size = _name.length;\n ...\n}\n```\n**GOOD:**\n\n```dart\nvoid print(String name) {\n var size = name.length;\n ...\n}\n```\n\n**OK:**\n\n```dart\n[1,2,3].map((_) => print('Hello'));\n```\n", "sinceDartSdk": "2.16.0", "sinceLinter": "1.15.0" }, @@ -1577,7 +1577,7 @@ "incompatible": [], "sets": [], "fixStatus": "needsEvaluation", - "details": "From the [style guide](https://dart.dev/guides/language/effective-dart/style/):\n\n**AVOID** defining a one-member abstract class when a simple function will do.\n\nUnlike Java, Dart has first-class functions, closures, and a nice light syntax\nfor using them. If all you need is something like a callback, just use a\nfunction. If you're defining a class and it only has a single abstract member\nwith a meaningless name like `call` or `invoke`, there is a good chance\nyou just want a function.\n\n**GOOD:**\n```dart\ntypedef Predicate = bool Function(item);\n```\n\n**BAD:**\n```dart\nabstract class Predicate {\n bool test(item);\n}\n```\n\n", + "details": "From the [style guide](https://dart.dev/guides/language/effective-dart/style/):\n\n**AVOID** defining a one-member abstract class when a simple function will do.\n\nUnlike Java, Dart has first-class functions, closures, and a nice light syntax\nfor using them. If all you need is something like a callback, just use a\nfunction. If you're defining a class and it only has a single abstract member\nwith a meaningless name like `call` or `invoke`, there is a good chance\nyou just want a function.\n\n**BAD:**\n```dart\nabstract class Predicate {\n bool test(item);\n}\n```\n\n**GOOD:**\n```dart\ntypedef Predicate = bool Function(item);\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.1" }, @@ -1616,7 +1616,7 @@ "incompatible": [], "sets": [], "fixStatus": "needsEvaluation", - "details": "**DO** provide doc comments for all public APIs.\n\nAs described in the [pub package layout doc](https://dart.dev/tools/pub/package-layout#implementation-files),\npublic APIs consist in everything in your package's `lib` folder, minus\nimplementation files in `lib/src`, adding elements explicitly exported with an\n`export` directive.\n\nFor example, given `lib/foo.dart`:\n```dart\nexport 'src/bar.dart' show Bar;\nexport 'src/baz.dart';\n\nclass Foo { }\n\nclass _Foo { }\n```\nits API includes:\n\n* `Foo` (but not `_Foo`)\n* `Bar` (exported) and\n* all *public* elements in `src/baz.dart`\n\nAll public API members should be documented with `///` doc-style comments.\n\n**GOOD:**\n```dart\n/// A Foo.\nabstract class Foo {\n /// Start foo-ing.\n void start() => _start();\n\n _start();\n}\n```\n\n**BAD:**\n```dart\nclass Bar {\n void bar();\n}\n```\n\nAdvice for writing good doc comments can be found in the\n[Doc Writing Guidelines](https://dart.dev/guides/language/effective-dart/documentation).\n\n", + "details": "**DO** provide doc comments for all public APIs.\n\nAs described in the [pub package layout doc](https://dart.dev/tools/pub/package-layout#implementation-files),\npublic APIs consist in everything in your package's `lib` folder, minus\nimplementation files in `lib/src`, adding elements explicitly exported with an\n`export` directive.\n\nFor example, given `lib/foo.dart`:\n```dart\nexport 'src/bar.dart' show Bar;\nexport 'src/baz.dart';\n\nclass Foo { }\n\nclass _Foo { }\n```\nits API includes:\n\n* `Foo` (but not `_Foo`)\n* `Bar` (exported) and\n* all *public* elements in `src/baz.dart`\n\nAll public API members should be documented with `///` doc-style comments.\n\n**BAD:**\n```dart\nclass Bar {\n void bar();\n}\n```\n\n**GOOD:**\n```dart\n/// A Foo.\nabstract class Foo {\n /// Start foo-ing.\n void start() => _start();\n\n _start();\n}\n```\n\nAdvice for writing good doc comments can be found in the\n[Doc Writing Guidelines](https://dart.dev/guides/language/effective-dart/documentation).\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.1" }, @@ -1671,7 +1671,7 @@ "incompatible": [], "sets": [], "fixStatus": "needsEvaluation", - "details": "**DO** put asserts in initializer lists.\n\n**GOOD:**\n```dart\nclass A {\n A(int a) : assert(a != 0);\n}\n```\n\n**BAD:**\n```dart\nclass A {\n A(int a) {\n assert(a != 0);\n }\n}\n```\n", + "details": "**DO** put asserts in initializer lists.\n\n**BAD:**\n```dart\nclass A {\n A(int a) {\n assert(a != 0);\n }\n}\n```\n\n**GOOD:**\n```dart\nclass A {\n A(int a) : assert(a != 0);\n}\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.33" }, @@ -1739,7 +1739,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "**PREFER** using `const` for instantiating constant constructors.\n\nIf a constructor can be invoked as const to produce a canonicalized instance,\nit's preferable to do so.\n\n**GOOD:**\n```dart\nclass A {\n const A();\n}\n\nvoid accessA() {\n A a = const A();\n}\n```\n\n**GOOD:**\n```dart\nclass A {\n final int x;\n\n const A(this.x);\n}\n\nA foo(int x) => new A(x);\n```\n\n**BAD:**\n```dart\nclass A {\n const A();\n}\n\nvoid accessA() {\n A a = new A();\n}\n```\n\n", + "details": "**PREFER** using `const` for instantiating constant constructors.\n\nIf a constructor can be invoked as const to produce a canonicalized instance,\nit's preferable to do so.\n\n**BAD:**\n```dart\nclass A {\n const A();\n}\n\nvoid accessA() {\n A a = new A();\n}\n```\n\n**GOOD:**\n```dart\nclass A {\n const A();\n}\n\nvoid accessA() {\n A a = const A();\n}\n```\n\n**GOOD:**\n```dart\nclass A {\n final int x;\n\n const A(this.x);\n}\n\nA foo(int x) => new A(x);\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.30" }, @@ -1753,7 +1753,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "**PREFER** declaring const constructors on `@immutable` classes.\n\nIf a class is immutable, it is usually a good idea to make its constructor a\nconst constructor.\n\n**GOOD:**\n```dart\n@immutable\nclass A {\n final a;\n const A(this.a);\n}\n```\n\n**BAD:**\n```dart\n@immutable\nclass A {\n final a;\n A(this.a);\n}\n```\n\n", + "details": "**PREFER** declaring const constructors on `@immutable` classes.\n\nIf a class is immutable, it is usually a good idea to make its constructor a\nconst constructor.\n\n**BAD:**\n```dart\n@immutable\nclass A {\n final a;\n A(this.a);\n}\n```\n\n**GOOD:**\n```dart\n@immutable\nclass A {\n final a;\n const A(this.a);\n}\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.33" }, @@ -1767,7 +1767,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "**PREFER** using `const` for const declarations.\n\nConst declarations are more hot-reload friendly and allow to use const\nconstructors if an instantiation references this declaration.\n\n**GOOD:**\n```dart\nconst o = [];\n\nclass A {\n static const o = [];\n}\n```\n\n**BAD:**\n```dart\nfinal o = const [];\n\nclass A {\n static final o = const [];\n}\n```\n\n", + "details": "**PREFER** using `const` for const declarations.\n\nConst declarations are more hot-reload friendly and allow to use const\nconstructors if an instantiation references this declaration.\n\n**BAD:**\n```dart\nfinal o = const [];\n\nclass A {\n static final o = const [];\n}\n```\n\n**GOOD:**\n```dart\nconst o = [];\n\nclass A {\n static const o = [];\n}\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.43" }, @@ -1808,7 +1808,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "**DON'T** use `indexOf` to see if a collection contains an element.\n\nCalling `indexOf` to see if a collection contains something is difficult to read\nand may have poor performance.\n\nInstead, prefer `contains`.\n\n**GOOD:**\n```dart\nif (!lunchBox.contains('sandwich')) return 'so hungry...';\n```\n\n**BAD:**\n```dart\nif (lunchBox.indexOf('sandwich') == -1) return 'so hungry...';\n```\n\n", + "details": "**DON'T** use `indexOf` to see if a collection contains an element.\n\nCalling `indexOf` to see if a collection contains something is difficult to read\nand may have poor performance.\n\nInstead, prefer `contains`.\n\n**BAD:**\n```dart\nif (lunchBox.indexOf('sandwich') == -1) return 'so hungry...';\n```\n\n**GOOD:**\n```dart\nif (!lunchBox.contains('sandwich')) return 'so hungry...';\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.30" }, @@ -2005,7 +2005,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "**DO** use initializing formals when possible.\n\nUsing initializing formals when possible makes your code more terse.\n\n**BAD:**\n```dart\nclass Point {\n num x, y;\n Point(num x, num y) {\n this.x = x;\n this.y = y;\n }\n}\n```\n\n**GOOD:**\n```dart\nclass Point {\n num x, y;\n Point(this.x, this.y);\n}\n```\n\n**BAD:**\n```dart\nclass Point {\n num x, y;\n Point({num x, num y}) {\n this.x = x;\n this.y = y;\n }\n}\n```\n\n**GOOD:**\n```dart\nclass Point {\n num x, y;\n Point({this.x, this.y});\n}\n```\n\n**NOTE**\nThis rule will not generate a lint for named parameters unless the parameter\nname and the field name are the same. The reason for this is that resolving\nsuch a lint would require either renaming the field or renaming the parameter,\nand both of those actions would potentially be a breaking change. For example,\nthe following will not generate a lint:\n\n```dart\nclass Point {\n bool isEnabled;\n Point({bool enabled}) {\n this.isEnabled = enabled; // OK\n }\n}\n```\n\n**NOTE**\nAlso note that it is possible to enforce a type that is stricter than the\ninitialized field with an initializing formal parameter. In the following\nexample the unnamed `Bid` constructor requires a non-null `int` despite\n`amount` being declared nullable (`int?`).\n\n```dart\nclass Bid {\n final int? amount;\n Bid(int this.amount);\n Bid.pass() : amount = null;\n}\n```\n", + "details": "**DO** use initializing formals when possible.\n\nUsing initializing formals when possible makes your code more terse.\n\n**BAD:**\n```dart\nclass Point {\n num x, y;\n Point(num x, num y) {\n this.x = x;\n this.y = y;\n }\n}\n```\n\n**GOOD:**\n```dart\nclass Point {\n num x, y;\n Point(this.x, this.y);\n}\n```\n\n**BAD:**\n```dart\nclass Point {\n num x, y;\n Point({num x, num y}) {\n this.x = x;\n this.y = y;\n }\n}\n```\n\n**GOOD:**\n```dart\nclass Point {\n num x, y;\n Point({this.x, this.y});\n}\n```\n\n**NOTE:**\nThis rule will not generate a lint for named parameters unless the parameter\nname and the field name are the same. The reason for this is that resolving\nsuch a lint would require either renaming the field or renaming the parameter,\nand both of those actions would potentially be a breaking change. For example,\nthe following will not generate a lint:\n\n```dart\nclass Point {\n bool isEnabled;\n Point({bool enabled}) {\n this.isEnabled = enabled; // OK\n }\n}\n```\n\n**NOTE:**\nAlso note that it is possible to enforce a type that is stricter than the\ninitialized field with an initializing formal parameter. In the following\nexample the unnamed `Bid` constructor requires a non-null `int` despite\n`amount` being declared nullable (`int?`).\n\n```dart\nclass Bid {\n final int? amount;\n Bid(int this.amount);\n Bid.pass() : amount = null;\n}\n```\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.30" }, @@ -2063,7 +2063,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "**DON'T** use `length` to see if a collection is empty.\n\nThe `Iterable` contract does not require that a collection know its length or be\nable to provide it in constant time. Calling `length` just to see if the\ncollection contains anything can be painfully slow.\n\nInstead, there are faster and more readable getters: `isEmpty` and\n`isNotEmpty`. Use the one that doesn't require you to negate the result.\n\n**GOOD:**\n```dart\nif (lunchBox.isEmpty) return 'so hungry...';\nif (words.isNotEmpty) return words.join(' ');\n```\n\n**BAD:**\n```dart\nif (lunchBox.length == 0) return 'so hungry...';\nif (words.length != 0) return words.join(' ');\n```\n\n", + "details": "**DON'T** use `length` to see if a collection is empty.\n\nThe `Iterable` contract does not require that a collection know its length or be\nable to provide it in constant time. Calling `length` just to see if the\ncollection contains anything can be painfully slow.\n\nInstead, there are faster and more readable getters: `isEmpty` and\n`isNotEmpty`. Use the one that doesn't require you to negate the result.\n\n**BAD:**\n```dart\nif (lunchBox.length == 0) return 'so hungry...';\nif (words.length != 0) return words.join(' ');\n```\n\n**GOOD:**\n```dart\nif (lunchBox.isEmpty) return 'so hungry...';\nif (words.isNotEmpty) return words.join(' ');\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.30" }, @@ -2079,7 +2079,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "**PREFER** `x.isNotEmpty` to `!x.isEmpty` for `Iterable` and `Map` instances.\n\nWhen testing whether an iterable or map is empty, prefer `isNotEmpty` over\n`!isEmpty` to improve code readability.\n\n**GOOD:**\n```dart\nif (todo.isNotEmpty) {\n sendResults(request, todo.isEmpty);\n}\n```\n\n**BAD:**\n```dart\nif (!sources.isEmpty) {\n process(sources);\n}\n```\n\n", + "details": "**PREFER** `x.isNotEmpty` to `!x.isEmpty` for `Iterable` and `Map` instances.\n\nWhen testing whether an iterable or map is empty, prefer `isNotEmpty` over\n`!isEmpty` to improve code readability.\n\n**BAD:**\n```dart\nif (!sources.isEmpty) {\n process(sources);\n}\n```\n\n**GOOD:**\n```dart\nif (todo.isNotEmpty) {\n sendResults(request, todo.isEmpty);\n}\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.5" }, @@ -2222,7 +2222,7 @@ "incompatible": [], "sets": [], "fixStatus": "needsEvaluation", - "details": "**DO** document all public members.\n\nAll non-overriding public members should be documented with `///` doc-style\ncomments.\n\n**GOOD:**\n```dart\n/// A good thing.\nabstract class Good {\n /// Start doing your thing.\n void start() => _start();\n\n _start();\n}\n```\n\n**BAD:**\n```dart\nclass Bad {\n void meh() { }\n}\n```\n\nIn case a public member overrides a member it is up to the declaring member\nto provide documentation. For example, in the following, `Sub` needn't\ndocument `init` (though it certainly may, if there's need).\n\n**GOOD:**\n```dart\n/// Base of all things.\nabstract class Base {\n /// Initialize the base.\n void init();\n}\n\n/// A sub base.\nclass Sub extends Base {\n @override\n void init() { ... }\n}\n```\n\nNote that consistent with `dart doc`, an exception to the rule is made when\ndocumented getters have corresponding undocumented setters. In this case the\nsetters inherit the docs from the getters.\n\n", + "details": "**DO** document all public members.\n\nAll non-overriding public members should be documented with `///` doc-style\ncomments.\n\n**BAD:**\n```dart\nclass Bad {\n void meh() { }\n}\n```\n\n**GOOD:**\n```dart\n/// A good thing.\nabstract class Good {\n /// Start doing your thing.\n void start() => _start();\n\n _start();\n}\n```\n\nIn case a public member overrides a member it is up to the declaring member\nto provide documentation. For example, in the following, `Sub` needn't\ndocument `init` (though it certainly may, if there's need).\n\n**GOOD:**\n```dart\n/// Base of all things.\nabstract class Base {\n /// Initialize the base.\n void init();\n}\n\n/// A sub base.\nclass Sub extends Base {\n @override\n void init() { ... }\n}\n```\n\nNote that consistent with `dart doc`, an exception to the rule is made when\ndocumented getters have corresponding undocumented setters. In this case the\nsetters inherit the docs from the getters.\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.11" }, @@ -2249,7 +2249,7 @@ "incompatible": [], "sets": [], "fixStatus": "hasFix", - "details": "**DO** use trailing commas for all function calls and declarations unless the\nfunction call or definition, from the start of the function name up to the\nclosing parenthesis, fits in a single line.\n\n**GOOD:**\n```dart\nvoid run() {\n method(\n 'does not fit on one line',\n 'test test test test test test test test test test test',\n );\n}\n```\n\n**BAD:**\n```dart\nvoid run() {\n method('does not fit on one line',\n 'test test test test test test test test test test test');\n}\n```\n\n**Exception:** If the final parameter/argument is positional (vs named) and is\neither a function literal implemented using curly braces, a literal map, a\nliteral set or a literal array. This exception only applies if the final\nparameter does not fit entirely on one line.\n\n**Note:** This lint rule assumes `dart format` has been run over the code and\nmay produce false positives until that has happened.\n\n", + "details": "**DO** use trailing commas for all function calls and declarations unless the\nfunction call or definition, from the start of the function name up to the\nclosing parenthesis, fits in a single line.\n\n**BAD:**\n```dart\nvoid run() {\n method('does not fit on one line',\n 'test test test test test test test test test test test');\n}\n```\n\n**GOOD:**\n```dart\nvoid run() {\n method(\n 'does not fit on one line',\n 'test test test test test test test test test test test',\n );\n}\n```\n\n**EXCEPTION:** If the final parameter/argument is positional (vs named) and is\neither a function literal implemented using curly braces, a literal map, a\nliteral set or a literal array. This exception only applies if the final\nparameter does not fit entirely on one line.\n\n**NOTE:** This lint rule assumes `dart format` has been run over the code and\nmay produce false positives until that has happened.\n\n", "sinceDartSdk": "2.14.0", "sinceLinter": "1.3.0" }, @@ -2316,7 +2316,7 @@ "incompatible": [], "sets": [], "fixStatus": "hasFix", - "details": "**DO** sort constructor declarations before other members.\n\n**GOOD:**\n```dart\nabstract class Animation {\n const Animation(this.value);\n double value;\n void addListener(VoidCallback listener);\n}\n```\n\n**BAD:**\n```dart\nabstract class Visitor {\n double value;\n visitSomething(Something s);\n Visitor();\n}\n```\n\n", + "details": "**DO** sort constructor declarations before other members.\n\n**BAD:**\n```dart\nabstract class Visitor {\n double value;\n visitSomething(Something s);\n Visitor();\n}\n```\n\n**GOOD:**\n```dart\nabstract class Animation {\n const Animation(this.value);\n double value;\n void addListener(VoidCallback listener);\n}\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.11" }, @@ -2328,7 +2328,7 @@ "incompatible": [], "sets": [], "fixStatus": "hasFix", - "details": "**DO** sort unnamed constructor declarations first, before named ones.\n\n**GOOD:**\n```dart\nabstract class CancelableFuture implements Future {\n factory CancelableFuture(computation()) => ...\n factory CancelableFuture.delayed(Duration duration, [computation()]) => ...\n ...\n}\n```\n\n**BAD:**\n```dart\nclass _PriorityItem {\n factory _PriorityItem.forName(bool isStatic, String name, _MemberKind kind) => ...\n _PriorityItem(this.isStatic, this.kind, this.isPrivate);\n ...\n}\n```\n\n", + "details": "**DO** sort unnamed constructor declarations first, before named ones.\n\n**BAD:**\n```dart\nclass _PriorityItem {\n factory _PriorityItem.forName(bool isStatic, String name, _MemberKind kind) => ...\n _PriorityItem(this.isStatic, this.kind, this.isPrivate);\n ...\n}\n```\n\n**GOOD:**\n```dart\nabstract class CancelableFuture implements Future {\n factory CancelableFuture(computation()) => ...\n factory CancelableFuture.delayed(Duration duration, [computation()]) => ...\n ...\n}\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.11" }, @@ -2340,7 +2340,7 @@ "incompatible": [], "sets": [], "fixStatus": "needsEvaluation", - "details": "From the [style guide](https://dart.dev/guides/language/effective-dart/style/):\n\n**DO** place the `super` call last in a constructor initialization list.\n\nField initializers are evaluated in the order that they appear in the\nconstructor initialization list. If you place a `super()` call in the middle of\nan initializer list, the superclass's initializers will be evaluated right then\nbefore evaluating the rest of the subclass's initializers.\n\nWhat it doesn't mean is that the superclass's constructor body will be executed\nthen. That always happens after all initializers are run regardless of where\n`super` appears. It's vanishingly rare that the order of initializers matters,\nso the placement of `super` in the list almost never matters either.\n\nGetting in the habit of placing it last improves consistency, visually\nreinforces when the superclass's constructor body is run, and may help\nperformance.\n\n**GOOD:**\n```dart\nView(Style style, List children)\n : _children = children,\n super(style) {\n```\n\n**BAD:**\n```dart\nView(Style style, List children)\n : super(style),\n _children = children {\n```\n\n**DEPRECATED:** In Dart 2, it is a compile-time error if a superinitializer\nappears in an initializer list at any other position than at the end so this\nrule is made redundant by the Dart analyzer's basic checks and is no longer\nnecessary.\n \nThe rule will be removed in a future Linter release.\n", + "details": "From the [style guide](https://dart.dev/guides/language/effective-dart/style/):\n\n**DO** place the `super` call last in a constructor initialization list.\n\nField initializers are evaluated in the order that they appear in the\nconstructor initialization list. If you place a `super()` call in the middle of\nan initializer list, the superclass's initializers will be evaluated right then\nbefore evaluating the rest of the subclass's initializers.\n\nWhat it doesn't mean is that the superclass's constructor body will be executed\nthen. That always happens after all initializers are run regardless of where\n`super` appears. It's vanishingly rare that the order of initializers matters,\nso the placement of `super` in the list almost never matters either.\n\nGetting in the habit of placing it last improves consistency, visually\nreinforces when the superclass's constructor body is run, and may help\nperformance.\n\n**BAD:**\n```dart\nView(Style style, List children)\n : super(style),\n _children = children {\n```\n\n**GOOD:**\n```dart\nView(Style style, List children)\n : _children = children,\n super(style) {\n```\n\n**DEPRECATED:** In Dart 2, it is a compile-time error if a superinitializer\nappears in an initializer list at any other position than at the end so this\nrule is made redundant by the Dart analyzer's basic checks and is no longer\nnecessary.\n \nThe rule will be removed in a future Linter release.\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.1" }, @@ -2364,7 +2364,7 @@ "incompatible": [], "sets": [], "fixStatus": "hasFix", - "details": "From [Effective Dart](https://dart.dev/guides/language/effective-dart/design#prefer-type-annotating-public-fields-and-top-level-variables-if-the-type-isnt-obvious):\n\n**PREFER** type annotating public APIs.\n\nType annotations are important documentation for how a library should be used.\nAnnotating the parameter and return types of public methods and functions helps\nusers understand what the API expects and what it provides.\n\nNote that if a public API accepts a range of values that Dart's type system\ncannot express, then it is acceptable to leave that untyped. In that case, the\nimplicit `dynamic` is the correct type for the API.\n\nFor code internal to a library (either private, or things like nested functions)\nannotate where you feel it helps, but don't feel that you *must* provide them.\n\n**BAD:**\n```dart\ninstall(id, destination) {\n // ...\n}\n```\n\nHere, it's unclear what `id` is. A string? And what is `destination`? A string\nor a `File` object? Is this method synchronous or asynchronous?\n\n**GOOD:**\n```dart\nFuture install(PackageId id, String destination) {\n // ...\n}\n```\n\nWith types, all of this is clarified.\n\n", + "details": "From [Effective Dart](https://dart.dev/guides/language/effective-dart/design#do-type-annotate-fields-and-top-level-variables-if-the-type-isnt-obvious):\n\n**PREFER** type annotating public APIs.\n\nType annotations are important documentation for how a library should be used.\nAnnotating the parameter and return types of public methods and functions helps\nusers understand what the API expects and what it provides.\n\nNote that if a public API accepts a range of values that Dart's type system\ncannot express, then it is acceptable to leave that untyped. In that case, the\nimplicit `dynamic` is the correct type for the API.\n\nFor code internal to a library (either private, or things like nested functions)\nannotate where you feel it helps, but don't feel that you *must* provide them.\n\n**BAD:**\n```dart\ninstall(id, destination) {\n // ...\n}\n```\n\nHere, it's unclear what `id` is. A string? And what is `destination`? A string\nor a `File` object? Is this method synchronous or asynchronous?\n\n**GOOD:**\n```dart\nFuture install(PackageId id, String destination) {\n // ...\n}\n```\n\nWith types, all of this is clarified.\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.5" }, @@ -2379,7 +2379,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "From the [style guide](https://dart.dev/guides/language/effective-dart/style/):\n\n**DON'T** type annotate initializing formals.\n\nIf a constructor parameter is using `this.x` to initialize a field, then the\ntype of the parameter is understood to be the same type as the field. If a \na constructor parameter is using `super.x` to forward to a super constructor,\nthen the type of the parameter is understood to be the same as the super\nconstructor parameter.\n\nType annotating an initializing formal with a different type than that of the\nfield is OK.\n\n**GOOD:**\n```dart\nclass Point {\n int x, y;\n Point(this.x, this.y);\n}\n```\n\n**BAD:**\n```dart\nclass Point {\n int x, y;\n Point(int this.x, int this.y);\n}\n```\n\n**GOOD:**\n```dart\nclass A {\n int a;\n A(this.a);\n}\n\nclass B extends A {\n B(super.a);\n}\n```\n\n**BAD:**\n```dart\nclass A {\n int a;\n A(this.a);\n}\n\nclass B extends A {\n B(int super.a);\n}\n```\n", + "details": "From the [style guide](https://dart.dev/guides/language/effective-dart/style/):\n\n**DON'T** type annotate initializing formals.\n\nIf a constructor parameter is using `this.x` to initialize a field, then the\ntype of the parameter is understood to be the same type as the field. If a \na constructor parameter is using `super.x` to forward to a super constructor,\nthen the type of the parameter is understood to be the same as the super\nconstructor parameter.\n\nType annotating an initializing formal with a different type than that of the\nfield is OK.\n\n**BAD:**\n```dart\nclass Point {\n int x, y;\n Point(int this.x, int this.y);\n}\n```\n\n**GOOD:**\n```dart\nclass Point {\n int x, y;\n Point(this.x, this.y);\n}\n```\n\n**BAD:**\n```dart\nclass A {\n int a;\n A(this.a);\n}\n\nclass B extends A {\n B(int super.a);\n}\n```\n\n**GOOD:**\n```dart\nclass A {\n int a;\n A(this.a);\n}\n\nclass B extends A {\n B(super.a);\n}\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.1" }, @@ -2391,7 +2391,7 @@ "incompatible": [], "sets": [], "fixStatus": "hasFix", - "details": "**DO** await functions that return a `Future` inside of an async function body.\n\nIt's easy to forget await in async methods as naming conventions usually don't\ntell us if a method is sync or async (except for some in `dart:io`).\n\nWhen you really _do_ want to start a fire-and-forget `Future`, the recommended\nway is to use `unawaited` from `dart:async`. The `// ignore` and\n`// ignore_for_file` comments also work.\n\n**GOOD:**\n```dart\nFuture doSomething() => ...;\n\nvoid main() async {\n await doSomething();\n\n unawaited(doSomething()); // Explicitly-ignored fire-and-forget.\n}\n```\n\n**BAD:**\n```dart\nvoid main() async {\n doSomething(); // Likely a bug.\n}\n```\n\n", + "details": "**DO** await functions that return a `Future` inside of an async function body.\n\nIt's easy to forget await in async methods as naming conventions usually don't\ntell us if a method is sync or async (except for some in `dart:io`).\n\nWhen you really _do_ want to start a fire-and-forget `Future`, the recommended\nway is to use `unawaited` from `dart:async`. The `// ignore` and\n`// ignore_for_file` comments also work.\n\n**BAD:**\n```dart\nvoid main() async {\n doSomething(); // Likely a bug.\n}\n```\n\n**GOOD:**\n```dart\nFuture doSomething() => ...;\n\nvoid main() async {\n await doSomething();\n\n unawaited(doSomething()); // Explicitly-ignored fire-and-forget.\n}\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.19" }, @@ -2418,7 +2418,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "**AVOID** using braces in interpolation when not needed.\n\nIf you're just interpolating a simple identifier, and it's not immediately\nfollowed by more alphanumeric text, the `{}` can and should be omitted.\n\n**GOOD:**\n```dart\nprint(\"Hi, $name!\");\n```\n\n**BAD:**\n```dart\nprint(\"Hi, ${name}!\");\n```\n\n", + "details": "**AVOID** using braces in interpolation when not needed.\n\nIf you're just interpolating a simple identifier, and it's not immediately\nfollowed by more alphanumeric text, the `{}` can and should be omitted.\n\n**BAD:**\n```dart\nprint(\"Hi, ${name}!\");\n```\n\n**GOOD:**\n```dart\nprint(\"Hi, $name!\");\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.30" }, @@ -2463,7 +2463,7 @@ ], "sets": [], "fixStatus": "hasFix", - "details": "**DON'T** use `final` for local variables.\n\n`var` is shorter, and `final` does not change the meaning of the code.\n\n**BAD:**\n```dart\nvoid badMethod() {\n final label = 'Final or var?';\n for (final char in ['v', 'a', 'r']) {\n print(char);\n }\n}\n```\n\n**GOOD:**\n```dart\nvoid goodMethod() {\n var label = 'Final or var?';\n for (var char in ['v', 'a', 'r']) {\n print(char);\n }\n}\n```\n", + "details": "Use `var`, not `final`, when declaring local variables.\n\nPer [Effective Dart](https://dart.dev/guides/language/effective-dart/usage#do-follow-a-consistent-rule-for-var-and-final-on-local-variables),\nthere are two styles in wide use. This rule enforces the `var` style.\nFor the alternative style that prefers `final`, enable `prefer_final_locals`\nand `prefer_final_in_for_each` instead.\n\nFor fields, `final` is always recommended; see the rule `prefer_final_fields`.\n\n**BAD:**\n```dart\nvoid badMethod() {\n final label = 'Final or var?';\n for (final char in ['v', 'a', 'r']) {\n print(char);\n }\n}\n```\n\n**GOOD:**\n```dart\nvoid goodMethod() {\n var label = 'Final or var?';\n for (var char in ['v', 'a', 'r']) {\n print(char);\n }\n}\n```\n", "sinceDartSdk": "2.7.0", "sinceLinter": "0.1.104" }, @@ -2478,7 +2478,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "From the [style guide](https://dart.dev/guides/language/effective-dart/style/):\n\n**AVOID** wrapping fields in getters and setters just to be \"safe\".\n\nIn Java and C#, it's common to hide all fields behind getters and setters (or\nproperties in C#), even if the implementation just forwards to the field. That\nway, if you ever need to do more work in those members, you can do it without needing\nto touch the callsites. This is because calling a getter method is different\nthan accessing a field in Java, and accessing a property isn't binary-compatible\nwith accessing a raw field in C#.\n\nDart doesn't have this limitation. Fields and getters/setters are completely\nindistinguishable. You can expose a field in a class and later wrap it in a\ngetter and setter without having to touch any code that uses that field.\n\n**GOOD:**\n\n```dart\nclass Box {\n var contents;\n}\n```\n\n**BAD:**\n\n```dart\nclass Box {\n var _contents;\n get contents => _contents;\n set contents(value) {\n _contents = value;\n }\n}\n```\n\n", + "details": "From the [style guide](https://dart.dev/guides/language/effective-dart/style/):\n\n**AVOID** wrapping fields in getters and setters just to be \"safe\".\n\nIn Java and C#, it's common to hide all fields behind getters and setters (or\nproperties in C#), even if the implementation just forwards to the field. That\nway, if you ever need to do more work in those members, you can do it without needing\nto touch the callsites. This is because calling a getter method is different\nthan accessing a field in Java, and accessing a property isn't binary-compatible\nwith accessing a raw field in C#.\n\nDart doesn't have this limitation. Fields and getters/setters are completely\nindistinguishable. You can expose a field in a class and later wrap it in a\ngetter and setter without having to touch any code that uses that field.\n\n**BAD:**\n```dart\nclass Box {\n var _contents;\n get contents => _contents;\n set contents(value) {\n _contents = value;\n }\n}\n```\n\n**GOOD:**\n```dart\nclass Box {\n var contents;\n}\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.1" }, @@ -2517,7 +2517,7 @@ "incompatible": [], "sets": [], "fixStatus": "needsEvaluation", - "details": "**DO** use library directives if you want to document a library and/or annotate \na library.\n\n**GOOD:**\n```dart\n/// This library does important things\nlibrary;\n```\n\n```dart\n@TestOn('js')\nlibrary;\n```\n\n**BAD:**\n```dart\nlibrary;\n```\n\nNOTE: Due to limitations with this lint, libraries with parts will not be\nflagged for unnecessary library directives.\n", + "details": "**DO** use library directives if you want to document a library and/or annotate \na library.\n\n**BAD:**\n```dart\nlibrary;\n```\n\n**GOOD:**\n```dart\n/// This library does important things\nlibrary;\n```\n\n```dart\n@TestOn('js')\nlibrary;\n```\n\nNOTE: Due to limitations with this lint, libraries with parts will not be\nflagged for unnecessary library directives.\n", "sinceDartSdk": "Unreleased", "sinceLinter": "1.29.0" }, @@ -2547,7 +2547,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "**AVOID** `null` in null-aware assignment.\n\nUsing `null` on the right-hand side of a null-aware assignment effectively makes\nthe assignment redundant.\n\n**GOOD:**\n```dart\nvar x;\nx ??= 1;\n```\n\n**BAD:**\n```dart\nvar x;\nx ??= null;\n```\n\n", + "details": "**AVOID** `null` in null-aware assignment.\n\nUsing `null` on the right-hand side of a null-aware assignment effectively makes\nthe assignment redundant.\n\n**BAD:**\n```dart\nvar x;\nx ??= null;\n```\n\n**GOOD:**\n```dart\nvar x;\nx ??= 1;\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.30" }, @@ -2586,7 +2586,7 @@ "flutter" ], "fixStatus": "hasFix", - "details": "**AVOID** using `null` as an operand in `if null` operators.\n\nUsing `null` in an `if null` operator is redundant, regardless of which side\n`null` is used on.\n\n**GOOD:**\n```dart\nvar x = a ?? 1;\n```\n\n**BAD:**\n```dart\nvar x = a ?? null;\nvar y = null ?? 1;\n```\n\n", + "details": "**AVOID** using `null` as an operand in `if null` operators.\n\nUsing `null` in an `if null` operator is redundant, regardless of which side\n`null` is used on.\n\n**BAD:**\n```dart\nvar x = a ?? null;\nvar y = null ?? 1;\n```\n\n**GOOD:**\n```dart\nvar x = a ?? 1;\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.30" }, @@ -2629,7 +2629,7 @@ "incompatible": [], "sets": [], "fixStatus": "hasFix", - "details": "**AVOID** using parentheses when not needed.\n\n**GOOD:**\n```dart\na = b;\n```\n\n**BAD:**\n```dart\na = (b);\n```\n\nParentheses are considered unnecessary if they do not change the meaning of the\ncode and they do not improve the readability of the code. The goal is not to\nforce all developers to maintain the expression precedence table in their heads,\nwhich is why the second condition is included. Examples of this condition\ninclude:\n\n* cascade expressions - it is sometimes not clear what the target of a cascade\n expression is, especially with assignments, or nested cascades. For example,\n the expression `a.b = (c..d)`.\n* expressions with whitespace between tokens - it can look very strange to see\n an expression like `!await foo` which is valid and equivalent to\n `!(await foo)`.\n* logical expressions - parentheses can improve the readability of the implicit\n grouping defined by precedence. For example, the expression\n `(a && b) || c && d`.\n", + "details": "**AVOID** using parentheses when not needed.\n\n**BAD:**\n```dart\na = (b);\n```\n\n**GOOD:**\n```dart\na = b;\n```\n\nParentheses are considered unnecessary if they do not change the meaning of the\ncode and they do not improve the readability of the code. The goal is not to\nforce all developers to maintain the expression precedence table in their heads,\nwhich is why the second condition is included. Examples of this condition\ninclude:\n\n* cascade expressions - it is sometimes not clear what the target of a cascade\n expression is, especially with assignments, or nested cascades. For example,\n the expression `a.b = (c..d)`.\n* expressions with whitespace between tokens - it can look very strange to see\n an expression like `!await foo` which is valid and equivalent to\n `!(await foo)`.\n* logical expressions - parentheses can improve the readability of the implicit\n grouping defined by precedence. For example, the expression\n `(a && b) || c && d`.\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.44" }, @@ -2922,7 +2922,7 @@ "incompatible": [], "sets": [], "fixStatus": "needsEvaluation", - "details": "From the [design guide](https://dart.dev/guides/language/effective-dart/design):\n\n**PREFER** naming a method to___() if it copies the object's state to a new object.\n\n**PREFER** naming a method as___() if it returns a different representation backed by the original object.\n\n**BAD:**\n```dart\nclass Bar {\n Foo myMethod() {\n return Foo.from(this);\n }\n}\n```\n\n**GOOD:**\n```dart\nclass Bar {\n Foo toFoo() {\n return Foo.from(this);\n }\n}\n```\n\n**GOOD:**\n```dart\nclass Bar {\n Foo asFoo() {\n return Foo.from(this);\n }\n}\n```\n\n", + "details": "From the [Effective Dart](https://dart.dev/guides/language/effective-dart/design):\n\n**PREFER** naming a method `to___()` if it copies the object's state to a new\nobject.\n\n**PREFER** naming a method `as___()` if it returns a different representation\nbacked by the original object.\n\n**BAD:**\n```dart\nclass Bar {\n Foo myMethod() {\n return Foo.from(this);\n }\n}\n```\n\n**GOOD:**\n```dart\nclass Bar {\n Foo toFoo() {\n return Foo.from(this);\n }\n}\n```\n\n**GOOD:**\n```dart\nclass Bar {\n Foo asFoo() {\n return Foo.from(this);\n }\n}\n```\n\n", "sinceDartSdk": "2.0.0", "sinceLinter": "0.1.31" }, From 2ec4a8382ed0f5ad46961976438f5b61c33ef9cd Mon Sep 17 00:00:00 2001 From: Parker Lougheed Date: Fri, 18 Nov 2022 17:24:08 -0600 Subject: [PATCH 24/32] Remove usage of diff2html (#4389) It was our only usage of diff2html and it wasn't working anyway. It's not worth the bloat with only one (simple) usage across the site. If we need it in the future, we can always properly add support. --- site-shared | 2 +- src/tools/pub/cmd/pub-outdated.md | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/site-shared b/site-shared index 3f55d0770..61dcf5820 160000 --- a/site-shared +++ b/site-shared @@ -1 +1 @@ -Subproject commit 3f55d07704b43696ee36ac281a364d4f3faa19d2 +Subproject commit 61dcf58208e249511261ec796c4005a8f4e049b2 diff --git a/src/tools/pub/cmd/pub-outdated.md b/src/tools/pub/cmd/pub-outdated.md index 0c7a6e249..81c658f32 100644 --- a/src/tools/pub/cmd/pub-outdated.md +++ b/src/tools/pub/cmd/pub-outdated.md @@ -1,7 +1,6 @@ --- title: dart pub outdated description: Use dart pub outdated to help you update your package dependencies. -diff2html: true --- _Outdated_ is one of the commands of the [pub tool](/tools/pub/cmd). @@ -96,10 +95,6 @@ the version in the **Resolvable** column In [caret syntax][], that's **`^0.12.1`**. Here's the diff for `pubspec.yaml`: -{% comment %} - [TODO: Improve the formatting of the following diff] -{% endcomment %} - ```diff - http: ^0.11.0 + http: ^0.12.1 From 26403831bbc68ae4e44015adbf21998266e5c7b1 Mon Sep 17 00:00:00 2001 From: Vini <50067152+viniciusddrft@users.noreply.github.com> Date: Sun, 20 Nov 2022 18:12:38 -0300 Subject: [PATCH 25/32] Update pubspec dependency constraints (#4392) Update dart-sdk -> 2.18.4 Update build_runner -> 2.3.2 Update lints -> 2.0.1 --- pubspec.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pubspec.yaml b/pubspec.yaml index 1f8867a93..2229df82d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,13 +3,13 @@ name: site_www homepage: https://dart.dev environment: - sdk: '>=2.18.1 <3.0.0' + sdk: '>=2.18.4 <3.0.0' dev_dependencies: - build_runner: ^2.1.0 + build_runner: ^2.3.2 code_excerpt_updater: path: site-shared/packages/code_excerpt_updater code_excerpter: path: site-shared/packages/code_excerpter linkcheck: ^2.0.19 - lints: ^2.0.0 + lints: ^2.0.1 From 9d67c7c448c73f906e2fd759b09470f95d69b879 Mon Sep 17 00:00:00 2001 From: Anthony Sansone Date: Mon, 21 Nov 2022 11:37:32 -0600 Subject: [PATCH 26/32] Update JS to Dart (#4354) [Staged page](https://dart--staging.web.app/guides/language/coming-from/js-to-dart). Original comments are in a [Google Doc](https://docs.google.com/document/d/1h7okBLXoKX2UuG7bXJSVcAQZiuV9AcRfoDKsxG5gMdg/edit#). --- site-shared | 2 +- .../language/coming-from/js-to-dart.md | 1760 +++++++++-------- 2 files changed, 913 insertions(+), 849 deletions(-) diff --git a/site-shared b/site-shared index 61dcf5820..3f55d0770 160000 --- a/site-shared +++ b/site-shared @@ -1 +1 @@ -Subproject commit 61dcf58208e249511261ec796c4005a8f4e049b2 +Subproject commit 3f55d07704b43696ee36ac281a364d4f3faa19d2 diff --git a/src/_guides/language/coming-from/js-to-dart.md b/src/_guides/language/coming-from/js-to-dart.md index 24ac40813..e3f07806a 100644 --- a/src/_guides/language/coming-from/js-to-dart.md +++ b/src/_guides/language/coming-from/js-to-dart.md @@ -3,101 +3,96 @@ title: Learning Dart as a JavaScript developer description: Leverage your JavaScript knowledge when learning Dart. --- -This guide aims to leverage your JavaScript (JS) -programming knowledge when learning Dart. -It showcases key similarities and differences -in both languages, and introduces Dart concepts -that are not present in vanilla JavaScript. -As a JavaScript developer, -Dart should feel quite familiar, -as both languages share many concepts. +This guide aims to leverage your JavaScript programming knowledge +when learning Dart. +It showcases key similarities and differences in both languages, +and introduces Dart concepts that unsupported in JavaScript. +As a JavaScript developer, Dart should feel quite familiar, +as both languages share many concepts. Like JavaScript, Dart runs on an event loop, so both languages execute code in a similar way. For example, asynchronous concepts like futures -(promises in JS) and the `async/await` syntax are very similar. +(promises in JavaScript) and the `async/await` syntax are very similar. Dart is strongly typed, unlike JavaScript. -If you are also familiar with TypeScript or tooling -that adds static typing (like Flow), then learning Dart -probably won't be much of an extra step for you. -However, if you've mostly worked with vanilla JavaScript, -it might take a bit more effort to adjust. -The good news is that since Dart is strongly typed, -many errors that might exist in JavaScript code are -caught even before compiling your Dart code. - -As of Dart 2.12, null safety is enabled by default, -which JavaScript doesn't support. As a JavaScript developer, +If you have used with TypeScript or Flow, +this should simplify learning Dart. +If you've mostly worked with pure JavaScript, +it might be more of an adjustment. +With strong typing, Dart catches many errors before compiling +that might exist in JavaScript code. + +Dart enables null safety by default. +JavaScript doesn't support null safety. +As a JavaScript developer, it might take a while to learn how to write null safe code, but the trade-off is better protection against null reference exceptions that are detected even before compiling Dart code. (Thereby avoiding those dreaded `TypeError`s that occur when doing operations -on a JS variable that turns out to be null.) +on a JavaScript variable that turns out to be null.) ## Conventions and linting -JavaScript and Dart both have linting tools -to enforce standard conventions. However, -while JavaScript has `ESLint` as a standalone tool -(among other available tooling), -and many different standards and configurations, -Dart has official layout conventions and includes -a linter to make compliance effortless. +JavaScript and Dart both have linting tools to enforce standard conventions. +While JavaScript offers many tools, standards, and configurations, +Dart has one official set of layout and style conventions plus a linter +to simplify compliance. +The Dart analyzer lints code along with providing more analytical functions. To customize the lint rules for your project, follow the [Customizing static analysis][] instructions. -{{site.alert.secondary}} - **Pro tip:** Dart provides [`dart fix`][], - which finds and fixes errors found by the analyzer. -{{site.alert.end}} +Dart provides [`dart fix`][] to find and fix errors. -Dart also provides a code formatter, -which is similar to JS tools like [Prettier][]. -Automatically format any Dart project by running -[`dart format`](/tools/dart-format) on the command line. -For Flutter, `flutter format` acts as an alias for this command. -(Note that the IDE plugins for Dart and Flutter -also provide this functionality.) +Dart also provides a code formatter similar to JavaScript tools like [Prettier][]. +To format code in any Dart project, run [`dart format`](/tools/dart-format) on +your command line. In Flutter, use `flutter format`. +The IDE plugins for Dart and Flutter also provide this ability. -{{site.alert.secondary}} - **Pro tip:** Dart supports optional trailing - commas for any comma-separated values, - such as function parameters or list items. - This causes the formatter to place each item - onto its own line, which helps with readability, - especially when you have a lot of nested code - (as can happen in Flutter layout code). -{{site.alert.end}} +Dart supports trailing commas for comma-separated lists of collections, +parameters, or arguments. When you add the trailing comma, +the formatter places each list item on its own line. +When you believe your list may have more items at a later date, +add the trailing comma. Avoid adding the trailing comma for the formatting +benefit alone. -For more information on using commas to make your code -read more like HTML, check out -[Using trailing commas][] on flutter.dev. +JavaScript supports trailing commas in list and map literals only. -For more information about Dart conventions and linting, -check out [Effective Dart][] and [Linter rules][]. +{{site.alert.secondary}} + To learn more about: + * Using commas to make your code read more like HTML, read + [Using trailing commas][] on flutter.dev. + * Linting Dart, read [Linter rules][]. + * Writing good Dart code, read [Effective Dart][]. +{{site.alert.end}} [Customizing static analysis]: /guides/language/analysis-options [`dart fix`]: /tools/dart-fix -[Effective Dart]: /guides/language/effective-dart +[Effective Dart]: /guides/language/effective-dart [Linter rules]: /tools/linter-rules [Prettier]: https://prettier.io/ [Using trailing commas]: {{site.flutter-docs}}/development/tools/formatting#using-trailing-commas - ## Built-in types -While both JavaScript and Dart have types, -only Dart is a strongly typed language. -This means that all Dart types have to be -inferrable by the analyzer, explicitly defined, -or assigned as `dynamic`, which disables static type -checking for that identifier. +Both JavaScript and Dart categorize their data into _types_. +Every variable has an associated type. +The type determines the kind of value the variable can store and +what operations can be performed on these values. +Dart differs from JavaScript in that it assigns a static type to every +variable and to every expression. +In Dart, the static type predicts the runtime type of the values of a +variable, or of the value of an expression. +Dart assigns a static type to every expression and variable. +In Dart, the static type predicts the runtime type of the value of an +expression. This means that Dart apps have sound static typing. + +JavaScript provides primitive types `num`, `string`, and `boolean` +and the `null` value as well as _arrays_ and a `Map` type. -Dart supports nullable and non-nullable versions -of the the following built-in types: +Dart supports built-in types include: * Numbers (`num`, `int`, `double`) * Strings (`String`) @@ -108,52 +103,46 @@ of the the following built-in types: * Symbols (`Symbol`) * The value `null` (`Null`) -For more information, check out -[Built-in types][] in the [Dart Language Tour][]. +To learn more, see [Built-in types][] in the [Dart Language Tour][]. -In Dart, all types are reference types, -meaning that all variables refer to an object -(an instance of a class). However, the types -`int`, `double`, `String`, and `bool` -are implemented to be immutable (unchanging) -and are canonicalized, -which means they behave as if they are value types. +All non-`Null` types in Dart are subtypes of Object. +All values are also objects. +Dart doesn't use “primitive types” like JavaScript. +By contrast, Dart normalizes or _canonicalizes_ number, boolean +and `null` values. +This means only one `int` value with the numerical value `1` exists. {{site.alert.note}} - JavaScript has two equality operators, - `==` and `===`. The `==` operator performs - the equality test after doing any necessary - type conversions. The `===` operator doesn't - perform type conversions. Dart doesn't have - an equivalent to `===`. + JavaScript has two equality operators, `==` and `===`. + The `==` operator performs the equality test after doing any necessary + type conversions on or to primitive values. + The `===` operator doesn't perform type conversions. + Dart uses the `identical` function to check if two values are the + same object, and the `==` operator to check whether the objects + consider themselves as equal. {{site.alert.end}} -For more information on these JavaScript operators, -check out [this question on Stack Overflow][]. - [Built-in types]: /guides/language/language-tour#built-in-types [Dart Language Tour]: /guides/language -[this question on Stack Overflow]: https://stackoverflow.com/questions/359494/which-equals-operator-vs-should-be-used-in-javascript-comparisons/359509#359509 -For example, the equals operator `==` and the `identical()` -method are guaranteed to return true for the -same values of these types, as shown in the following code: +For example: +The equals operator `==` and the `identical()` method return `true` +for the same values of number types. Review the example shown in the +following code: {:.include-lang} ```dart -var a = 1; -var b = 1; +var a = 2; +var b = 1 + 1; print(a == b); // Prints true -print(identical(a, b)); // Prints true +print(identical(a, b)); // Prints true; only one "2" object exists ``` -The next section covers basic types. -Other types are covered later in this page, -including collection types (lists, maps) -and types that aid asynchrony (futures, streams). +### Primitive Types -### Numbers +This section covers how Dart represents primitive types from JavaScript. +#### Numbers Dart has three data types for holding numbers: @@ -161,90 +150,98 @@ Dart has three data types for holding numbers: : The equivalent to the generic number type in JavaScript. `int` -: Any numeric value without a decimal point. +: A numeric value without a fractional part. `double` -: Any numeric value, including those with a decimal point. +: Any 64-bit (double-precision) floating point number. -All these types are also classes within the Dart API. +The Dart API includes all these types as classes. Both the `int` and `double` types share `num` as their parent class: num subclasses Object and int and double each subclass num -As number values are technically class instances, -they have the convenience of exposing their own -utility functions. Because of this, a `double` can, -for example, be rounded up as follows: +As Dart considers numbers as objects, numbers can expose their +own utility functions as object methods. +You don't need to use an additional object to apply a function to a number. -{:.include-lang} -```dart -var rounded = 2.5.round(); -``` +For example, to round a `double` to an integer: {:.include-lang} ```js let rounded = Math.round(2.5); ``` -### Strings +{:.include-lang} +```dart +var rounded = 2.5.round(); +``` + +#### Strings -Strings in Dart work similarly to strings in JavaScript. -String literals are defined using single quotation marks (`'`), -but can also be defined using double quotation marks -to enable use of single quotation marks within the string -without escaping. However, single quotes are preferred. +Strings in Dart work like strings in JavaScript. +To write a string literal, enclose it in single (`'`) or double (`"`) +quotation marks. +The majority of Dart developers use single quotes, +but the language enforces no standard. +Use double quotation marks if you don't want to escape +single quotes within the string. {:.include-lang} ```dart var a = 'This is a string.'; ``` -#### Escaping special characters +##### Escaping special characters -Escaping special characters in Dart is similar -to JavaScript (and most other languages). -To include special characters escape them -using the backslash character. +To include a character with another meaning in a string, +like a `$` used for string interpolation, you must escape that character. +Escaping special characters in Dart works like JavaScript +and most other languages. +To escape special characters, +precede that character with the backslash character (`\`). -The following code shows some examples. +The following code shows some examples. {:.include-lang} ```dart final singleQuotes = 'I\'m learning Dart'; // I'm learning Dart final doubleQuotes = "Escaping the \" character"; // Escaping the " character +final dollarEscape = 'The price is \$3.14.'; // The price is $3.14. +final backslashEscape = 'The Dart string escape character is \\.'; final unicode = '\u{1F60E}'; // 😎, Unicode scalar U+1F60E ``` -Note that 4-digit hexadecimal values can also be used directly -(for example, `\u2665`), however, curly braces also work. -For more information on working with unicode characters, -check out [Runes and grapheme clusters][]. +{{site.alert.note}} + You can use four-digit hexadecimal characters with or without curly braces. + To learn more about working with unicode characters, + see [Runes and grapheme clusters][]. +{{site.alert.end}} [Runes and grapheme clusters]: /guides/language/language-tour#characters -#### String interpolation +##### String interpolation + +JavaScript supports template literals. +These use backtick (`` ` ``) character delimiters for the following reasons: -JavaScript supports template literals, -which are literals delimited with backtick (`` ` ``) characters, -allowing for multiline strings, -for string interpolation with embedded expressions, -and for special constructs called tagged templates. -Dart supports string concatenation and interpolation -with embedded expressions as part of standard string literals, -meaning that you aren't required to enclose the string in -backticks to enable that functionality. -For more information, -check out [Strings][] in the [Dart Language Tour][]. +* To allow for multiline strings +* To interpolate strings with embedded expressions +* To create special constructs called tagged templates + +In Dart, you don't need to enclose a string in backticks to concatenate +strings or use interpolations within string literals. + +To learn more, see [Strings][] in the [Dart Language Tour][]. [Strings]: /guides/language/language-tour#strings As in JavaScript template literals, -insert expressions into the string literal -using the `${}` syntax. -Dart expands on this by allowing the curly braces -to be omitted when the expression is a single identifier: +you can use the `${}` syntax to insert expressions into +a string literal. +Dart uses this syntax and allows you to omit the curly braces +when the expression uses a single identifier. {:.include-lang} ```dart @@ -257,12 +254,12 @@ var str = 'I eat ${food}'; // I eat bread In JavaScript, you can define multiline strings using template literals. -Dart has two ways to define multiline strings: +Dart has two ways to define multiline strings.
  1. Using implicit string concatenation: - Any neighboring string literals are automatically - concatenated, even when they are spread over multiple lines: + Dart concantenates any neighboring string literals, + even when spread over multiple lines: {:.include-lang} ```dart @@ -274,15 +271,18 @@ final s1 = 'String '
  2. Using a multi line string literal: When using three quotation marks (either single or double) -on either side of the string, -the literal is allowed to span multiple lines: +on either side of the string, the literal can span multiple lines. + {:.include-lang} ```dart -final s2 = '''You can create -multiline strings like this one.'''; +final s2 = ''' +You can create +multiline strings like this one. +'''; -final s3 = """This is also a +final s3 = """ +This is also a multiline string."""; ```
  3. @@ -290,10 +290,9 @@ multiline string."""; #### Equality -As in JavaScript, use the equal-to operator (`==`) -to determine if two strings are equal. -Two strings are equal if they contain the same -sequence of code units. +Dart considers two strings equal when they contain the same sequence +of code units. To determine if two strings have the same sequences, +use the equal-to operator (`==`). {:.include-lang} ```dart @@ -305,165 +304,170 @@ assert(s1 == 'line breaks.'); ``` -### Booleans +#### Booleans -Both Dart and JavaScript booleans represent -a binary value. Each language has two objects -that hold this type: the boolean literals `true` and `false`, -which are compile-time constants in both languages. +Boolean values in both Dart and Javascript express a binary condition. +These two values represent whether a value or expression is +`true` or `false`. +You can return the values using the literals `true` and `false`, +or produced them using expressions like `x < 5` or `y == null`. {:.include-lang} -```dart -var a = true; +```js +let isBananaPeeled = false; ``` + {:.include-lang} -```js -let a = true; +```dart +var isBananaPeeled = false; ``` ## Variables -Variables in Dart are similar to variables in JavaScript, -with the following caveats: +Variables in Dart work like variables in JavaScript, +with two exceptions: -* As Dart is a statically typed language, - when declaring variables the type has to be - inferrable, or you must explicitly define the - type when initializing the variable. +1. Each variable has a type. +1. Dart scopes all variables at the block level, + like `let` and `const` variables in JavaScript. -* All variables in Dart are block scoped, - as you would expect with `let` or `const` in JavaScript. +A Dart variable gets its type in one of two ways: -Declaring and initializing variables in Dart works -almost identically to JavaScript: +1. Declared: A type written in the declaration +1. Inferred: An expression used to initialize the variable + By convention, use `var` or `final` when the analyzer can infer the type. {:.include-lang} -```dart -// Declare a variable -var name; -// Initialize the variable -name = 'bob'; +```js // Declare and initialize a variable at once -var name = 'bob'; +let name = "bob"; ``` {:.include-lang} -```js -// Declare a variable -let name; -// Initialize the variable -name = "bob"; -// Declare and initialize a variable at once -let name = "bob"; +```dart +// Declare a variable with a specific type +// when you don't provide an initial value +String name; +// Declare and initialize a variable +// at the same time and Dart infers +// the type +var name = 'bob'; ``` -Note that you can replace var in Dart with -an explicit type. However, by convention, -var is recommended when the analyzer can -implicitly infer the type. +Variables can only accept values of their type. {:.include-lang} ```dart -String name = 'bob'; // This is the same as 'var', - // since Dart infers the type to be String. +var name = 'bob'; +name = 5; // Forbidden, as `name` has type `String`. ``` -When a variable without an explicit type -is initialized after its declaration, -its type is inferred as the catch-all `dynamic` type. -Likewise, when a type cannot be automatically inferred, -it defaults back to the `dynamic` type. +If you don't provide an initial value or explicit type, +Dart infers the variable's type to be the catch-all type `dynamic`. + +Like JavaScript variables, you can assign any value to Dart variables +that use the `dynamic` type. -Unlike JavaScript, a Dart variable's type can't be changed -after initialization: +{:.include-lang} +```js +// Declare a variable +let name; +// Initialize the variable +name = "bob"; +``` {:.include-lang} ```dart -// Variable initialized later, `name` has type `dynamic`. -var name; +// Declare a variable without a type or assigned value +// and Dart infers the 'dynamic' type +var name; +// Initialize the variable and the type remains `dynamic` name = 'bob'; - name = 5; // Allowed, as `name` has type `dynamic`. - -// Variable initialized immediately, `name` has type `String`. -var name = 'bob'; - -name = 5; // Forbidden, as `name` has type `String`. ``` ### Final and const -The final modifier in Dart acts like the const -modifier in JavaScript: +Both JavaScript and Dart use variable modifiers. Both use `const`, but +differ in how `const` works. Where JavaScript would use `const`, +Dart uses `final`. -
      -
    1. The variable must be initialized - immediately upon declaration. +When you add `final` to a Dart variable or `const` to a JavaScript variable, +you must initialize the variable before other code can read its value. +Once initialized, you can't change these variables' references. -{{site.alert.note}} - One exception to this is with class fields, - which might be initialized in the class constructor. - Learn more in the [Classes](#classes) section. -{{site.alert.end}} -
    2. +When Dart uses `const`, it refers to special values that it creates +when compiling. +Dart uses limited expressions to create these immutable values. +These expressions _cannot_ have side effects. +Under these conditions, the compiler can then predict the precise value +of a constant variable or expression, not just its static type. -
    3. Once the variable has been initialized, - its reference can't be changed later. -
    4. -
    +{:.include-lang} +```dart +final String name; +// Cannot read name here, not initialized. +if (useNickname) { + name = "Bob"; +} else { + name = "Robert"; +} +print(name); // Properly initialized here. +``` -The `const` modifier in Dart acts the same as its -`final` modifier, except that its value must -be known at compile time. Since JavaScript is an -interpreted language requiring no compilation step, -it doesn’t have an equivalent. +{{site.alert.note}} +When you create an object, the class constructor must initialize the +`final` instance variables. +This ensures that these variables have a value before anyone can read them. -Although you can't modify a `const` object in JS, -you can modify its fields. In comparison, -you can't change a Dart `const` object or its fields: -they're _immutable_ (they can't be changed). +Learn more in the [Classes](#classes) section. +{{site.alert.end}} -In Dart, **constant variables must contain constant values**. -However, non-constant variables can still contain -constant values, and values themselves can also be marked `const`. +In Dart, _constant variables must contain constant values_. +Non-constant variables can contain constant values that +you can also mark as `const`. {:.include-lang} ```dart -var foo = const []; // foo is not constant, but the value it points to is. +var foo = const []; + // foo is not constant, but the value it points to is. // You can reassign foo to a different list value, - // but its current list value cannot be altered. + // but its current list value cannot be altered. const baz = []; // Equivalent to `const []` ``` Likewise, classes can have their own `const` constructors -that produce immutable instances. For more information, -check out the [Classes](#classes) section. +that produce immutable instances. + +You can't modify a `const` variable in JavaScript or Dart. +JavaScript does allow you to modify a `const` object's fields, but +Dart does not. + +To learn more, see the [Classes](#classes) section. -## Null safety +## Null safety -Unlike vanilla JavaScript, -Dart supports null safety, making any type non-nullable -by default (as of Dart 2.12). One key benefit of this is -that null reference exceptions are caught when writing code, -so they are unlikely to occur at runtime. +Unlike JavaScript, Dart supports null safety. +In Dart, all types default to non-nullable. +This benefits Dart developers because Dart catches null reference +exceptions when writing code, rather than at runtime. ### Nullable vs non-nullable types -For example, all the variables in the following code -are non-nullable: +None of the variables in the following code example can be `null`. {:.include-lang} ```dart // In null-safe Dart, none of these can ever be null. var i = 42; // Inferred to be an int. String name = getFileName(); -final b = Foo(); +final b = Foo(); // Foo() invokes a constructor ``` To indicate that a variable might have the value `null`, -just add `?` to its type declaration: +add `?` to its type declaration: {:.include-lang} ```dart @@ -486,24 +490,21 @@ String returnsNonNullable() { } ``` -### Null-aware operators +### Null-aware operators Dart supports several operators to deal with nullability. -As in JavaScript, the null assignment operator (`??=`), -null coalescing operator (`??`), -and optional chaining operator (`?.`), -are all available in Dart and operate the same as in JavaScript. +As in JavaScript, Dart supports the null assignment operator (`??=`), +null-coalescing operator (`??`), and optional chaining operator (`?.`). +These operators work the same as JavaScript. #### ! Operator -In cases where it's safe to assume that a -nullable variable or expression is in fact non-null, -it's possible to tell the compiler to repress any -compile time errors. This is done using the (`!`) operator, -by placing it as a suffix to the expression. -(Don't confuse this with Dart's not (`!`) operator, -which uses the same symbol but is always prefixed -to the expression.) +In cases where a nullable variable or expression might be non-null, +you can tell the compiler to repress any compile time errors +using the (`!`) operator. Place this operator after the expression. + +Don't confuse this with Dart's not (`!`) operator, +which uses the same symbol but place before the expression. {:.include-lang} ```dart @@ -541,9 +542,9 @@ whether at the top level, as a class field, or in the local scope. {:.include-lang} -```dart +```js // On the top level -multiply(a, b) { +function multiply(a, b) { return a * b; } @@ -555,19 +556,19 @@ class Multiplier { } // In a local scope -main() { - multiply(a, b) { +function main() { + function multiply(a, b) { return a * b; } - print(multiply(3, 4)); + console.log(multiply(3, 4)); } ``` {:.include-lang} -```js +```dart // On the top level -function multiply(a, b) { +int multiply(a, b) { return a * b; } @@ -579,20 +580,20 @@ class Multiplier { } // In a local scope -function main() { - function multiply(a, b) { +main() { + multiply(a, b) { return a * b; } - console.log(multiply(3, 4)); + print(multiply(3, 4)); } ``` ### Arrow syntax Both Dart and JavaScript support arrow syntax (`=>`), -but they are different. -In Dart, arrow syntax is only used when the function +but differ in how they support it. +In Dart, you can only use the arrow syntax when the function contains a single expression or return statement. For example, the following `isNoble` functions are equivalent: @@ -611,15 +612,13 @@ bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null; ### Parameters -In JavaScript, -all parameters are _optional_ positioned parameters. -In Dart, this is not the case. -By default, all standard parameters are _required_ -positional parameters and must be provided when calling a function. +In JavaScript, all parameters _can_ be positional parameters. +By default, Dart _requires_ you to pass all parameters as arguments +to functions. {:.include-lang} ```dart -multiply(int a, int b) { +int multiply(int a, int b) { return a * b; } @@ -634,17 +633,16 @@ This can change in two situations: 1. The positional parameters are marked as optional. 1. The parameters are named and not marked as required. -Define optional positional parameters by enclosing them -in square brackets following the required positional -parameters, if they exist. You can't define required -parameters after an optional parameter. +To define optional positional parameters, enclose them +in square brackets following any required positional parameters. +You can't follow optional parameters with required parameters. Due to null safety, optional positional parameters must have a default value or be marked as nullable. -Learn more in the preceding section about [null safety](#null-safety). +To learn more, see the preceding section about [null safety](#null-safety). The following code has one valid and two invalid examples -of functions that define optional positional parameters: +of functions that define optional positional parameters. {:.include-lang} ```dart @@ -656,13 +654,14 @@ multiply(int a, [int b = 5, int? c]) { multiply(int a, [int b = 5], int c) { ... } -// Invalid: Neither positional parameter has a default value or has been flagged as nullable. +// Invalid: Neither positional parameter has a default +// value or has been flagged as nullable. multiply(int a, [int b, int c]) { ... } ``` -Here are some examples of calling a function that has optional parameters: +The following example shows how to call a function with optional parameters: {:.include-lang} ```dart @@ -692,20 +691,19 @@ pass values by prefixing the passed value with the name of the parameter, separated by a colon. For example, `f(namedParameter: 5)`. -Again, with null safety, -named parameters that are not flagged as required -either need to have a default value or be flagged as nullable. +Again, with null safety, named parameters that are not flagged as +required either need to have a default value or be flagged as nullable. The following code defines a function with named parameters: {:.include-lang} ```dart -// Valid: +// Valid: // - `a` has been flagged as required -// - `b` has a default value of 5 +// - `b` has a default value of 5 // - `c` is marked as nullable // - Named parameters follow the positional one -multiply(bool x, { required int a, int b = 5, int? c}) { +multiply(bool x, {required int a, int b = 5, int? c}) { ... } ``` @@ -714,7 +712,7 @@ The following examples call a function with named parameters: {:.include-lang} ```dart -// All are valid function calls. +// All are valid function calls. // Beyond providing the required positional parameter: multiply(false, a: 3); // Only provide required named parameters multiply(false, a: 3, b: 9); // Override default value of `b` @@ -723,9 +721,8 @@ multiply(false, c: 9, a: 3, b: 2); // Provide all named parameters out of order ### First-class functions -As in JavaScript, -functions are first-class citizens in Dart, -which means that they're treated as any other object. +JavaScript and Dart treat functions as first-class citizens. +This means that Dart treats functions as any other object. For example, the following code shows how to pass a function as a parameter to another function: @@ -757,81 +754,102 @@ JavaScript has two ways to declare an anonymous function: 1. Use a standard function expression 2. Use arrow syntax -For example: +Likewise, Dart also has two ways to declare anonymous functions. +Both work in a similar manner to the JavaScript arrow expression. +Dart's anonymous functions do not support the extra functionality +that comes with regular function expressions. +For example, JavaScript's support for a function expression acting +like a constructor, or creating a custom binding to this. + +To learn more, see the [Classes](#classes) section. {:.include-lang} ```js -// A regular function expression, assigned to a variable -let funcExpr = function(a, b) { return a * b; } -// The same anonymous function as an arrow function expression, with curly braces. -let arrowFuncExpr = (a, b) => { return a * b; } -// An arrow function with only one return statement as its contents does not require a block. +// A regular function expression +// assigned to a variable +let funcExpr = function(a, b) { + return a * b; +} +// The same anonymous function +// expressed as an arrow +// function with curly braces. +let arrowFuncExpr = (a, b) => { + return a * b; +} +// An arrow function with only +// one return statement as +// its contents does not +// require a block. let arrowFuncExpr2 = (a, b) => a * b; ``` -Likewise, Dart also has two ways to declare -anonymous functions, though both are functionally -similar to the arrow expression in JavaScript. -The extra functionality that comes with regular -function expressions (for example, -JavaScript's support for a function expression acting -like a constructor, or creating a custom binding to this), -aren't supported in Dart's anonymous functions. -(For more information, -check out the [Classes](#classes) section). - {:.include-lang} ```dart -// Assigning an anonymous function to a variable. -var blockFunc = (int a, int b) { - var c = a * b; - return c; -} +// Assign an anonymous function +// to a variable. +var blockFunc = + optionalCallback ?? (int a, int b) { + return a * b; +}; -// In the case of a single returned expression, -// you can shorten the syntax: +// For an expression with only a return statement, +// you can use the arrow syntax: var singleFunc = (int a, int b) => a * b; ``` -As with JavaScript, anonymous functions -can also be passed to other functions. -This is commonly used (in both languages) -when using the `map` function +As with JavaScript, you can pass anonymous functions to other functions. +Developers often pass anonymous functions when using the `map` function for arrays and lists: {:.include-lang} ```js -[1, 2, 3].map(e => e + 3); // [4, 5, 6] -[1, 2, 3].map(e => { +// returns [4, 5, 6] +[1, 2, 3].map(e => e + 3); + +// returns [5, 7, 9] +[1, 2, 3].map(e => { e *= 2; return e + 3; -}); // [5, 7, 9] +}); ``` {:.include-lang} ```dart -[1, 2, 3].map((e) => e + 3).toList(); // [4, 5, 6] -[1, 2, 3].map((e) { +// returns [4, 5, 6] +[1, 2, 3].map((e) => e + 3).toList(); + +// returns [5, 7, 9] +var list2 = [1, 2, 3].map((e) { e *= 2; return e + 3; -}).toList(); // [5, 7, 9] +}).toList(); ``` {{site.alert.note}} - The `map` function in these examples returns + The `map` function in the previous examples returns an `Iterable, rather than a `List`. - Therefore, the `toList` function converts the - returned `Iterable` back to a `List`. + The `toList` function converts the returned + `Iterable` back to a `List`. + + A list literal could achieve the same goal. + + {:.include-lang} + ```dart + // These two statements are equivalent: + print([for (var e in [1, 2, 3]) e + 3]); + print([1, 2, 3].map((e) => e + 3).toList()); + ``` {{site.alert.end}} ### Generator functions -Dart supports [_generator functions_] -that return an iterable collection of items -that are lazily built to improve the UI’s performance. -Convert a function to a generator function by adding -the `sync*` keyword after the function parameters, -and modify it to return an `Iterable`. +Both languages support [_generator functions_]. +These functions return an iterable collection of items +computed to avoid unncessary work. + +To write a generator function in Dart, +add the `sync*` keyword after the function parameters, +and return an `Iterable`. Add items to the final iterable using the `yield` keyword, or add whole sets of items using `yield*`. @@ -840,30 +858,67 @@ Add items to the final iterable using the The following example shows how to write a basic generator function: + +{:.include-lang} +```js +function* naturalsTo(n) { + let k = 0; + while (k < n) { + yield k++; + } +} + +// Returns [0, 1, 2, 3, 4] +for (let value of naturalsTo(5)) { + console.log(value); +} + +``` + + {:.include-lang} ```dart Iterable naturalsTo(int n) sync* { int k = 0; - while (k < n) { + while (k < n) { yield k++; } } -print(naturalsTo(5)); // Returns an iterable with [0, 1, 2, 3, 4]. +// Returns an iterable with [0, 1, 2, 3, 4] +print(naturalsTo(5).toList()); +``` +{:.include-lang} +```js +function* doubleNaturalsTo(n) { + let k = 0; + while (k < n) { + yield* [k, k]; + k++; + } +} + +// Returns [0, 0, 1, 1, 2, 2] +for (let value of doubleNaturalsTo(3)) { + console.log(value); +} +``` + +{:.include-lang} +```dart Iterable doubleNaturalsTo(int n) sync* { int k = 0; - while (k < n) { - yield* [k, k]; + while (k < n) { + yield* [k, k]; k++; } } -print(doubleNaturalsTo(3)); // Returns an iterable with [0, 0, 1, 1, 2, 2]. +// Returns an iterable with [0, 0, 1, 1, 2, 2] +print(doubleNaturalsTo(3)); ``` -This is a synchronous generator function, -and is not available in JavaScript. You can also define asynchronous generator functions, which return streams instead of iterables. Learn more in the upcoming [Asynchrony](#asynchrony) section. @@ -873,33 +928,24 @@ Learn more in the upcoming [Asynchrony](#asynchrony) section. This section describes differences in statements between JavaScript and Dart. -### Control flow (if/else, for, while, switch) +### Control flow (if/else, for, while, switch) -Nearly all control statements work similarly -to their JavaScript counterparts, -although some have additional uses when it comes -to collections -(discussed in more detail in the [Collections](#collections) section). +Most control statements work like their JavaScript counterparts. +Some have additional uses for [Collections](#collections). #### Iteration While both JavaScript and Dart have `for-in` loops, -their behavior is different. +their behaviors differ. -JavaScript's `for-in` loop iterates over an object's properties, -so to iterate over an iterable object's elements, -you must instead `for-of` or `Array.forEach()`. -Dart's `for-in` loop does this natively. +JavaScript's `for-in` loop iterates over an object's properties. +To iterate over a JavaScript iterable object's elements, +you must use `for-of` or `Array.forEach()`. +Dart's `for-in` loop works like JavaScripts `for-of`. The following example shows iterating over a collection and printing out each element: -{:.include-lang} -```dart -for (final element in list) { - print(element) -} -``` {:.include-lang} ```js @@ -908,13 +954,20 @@ for (const element of list) { } ``` +{:.include-lang} +```dart +for (final element in list) { + print(element) +} +``` + #### Switch {{site.alert.note}} One key difference with the `switch` statement in JavaScript and Dart: when a case has no `break`, `continue`, or `return` statement, - JS allows execution to fall through and continue + JavaScript allows execution to fall through and continue with the next statement. However, Dart only allows this when a case's body is empty. {{site.alert.end}} @@ -938,30 +991,27 @@ switch (testEnum) { ### Operators Both Dart and JavaScript contain predefined operators. -Adding new operators is not supported in either language, -but Dart allows you to overload existing operators +Neither language supports adding new operators. +Dart supports overloading some existing operators with the `operator` keyword. For example: {:.include-lang} ```dart -class Box { - Box({ - required this.length, - required this.width, - required this.height, - }); - - final double length; - final double width; - final double height; - - Box operator +(Box x) { - return Box( - length: length + x.length, - width: width + x.width, - height: height + x.height, - ); - } +class Vector { + final double x; + final double y; + final double z; + Vector(this.x, this.y, this.z); + Vector operator +(Vector other) => Vector( + x + other.x, + y + other.y, + z + other.z, + ); + Vector operator *(double scalar) => Vector( + x * scalar, + y * scalar, + z * scalar, + ); } ``` @@ -970,22 +1020,21 @@ class Box { The equality and relational operators of both languages are almost identical, as shown in the following table: -| Meaning | Dart operator | JS equivalent | -|---------------------------------------------------|-----------------|---------------| -| Add | `+` | `+` | -| Subtract | `-` | `-` | -| Unary minus, also known as negation | `-expr` | `-expr` | -| Multiply | `*` | `*` | -| Divide | `/` | `/` | -| Divide returning an integer result | `~/` | | -| Get the remainder of an integer division (modulo) | `%` | `%` | -| `var = var + 1` (expression value is `var + 1`) | `++var` | `++var` | -| `var = var + 1` (expression value is `var`) | `var++` | `var++` | -| `var = var - 1` (expression value is `var - 1`) | `--var` | `--var` | -| `var = var - 1` (expression value is `var`) | `var--` | `var--` | +| Meaning | JavaScript operator | Dart operator | +|---------------------------------------------------|---------------------|---------------| +| Add | `+` | `+` | +| Subtract | `-` | `-` | +| Unary minus, also known as negation | `-expr` | `-expr` | +| Multiply | `*` | `*` | +| Divide | `/` | `/` | +| Divide returning an integer result | | `~/` | +| Get the remainder of an integer division (modulo) | `%` | `%` | +| `x = x + 1` (expression value is `x + 1`) | `++x` | `++x` | +| `x = x + 1` (expression value is `x`) | `x++` | `x++` | +| `x = x - 1` (expression value is `x - 1`) | `--x` | `--x` | +| `x = x - 1` (expression value is `x`) | `x--` | `x--` | {:.table .table-striped} - For example: {:.include-lang} @@ -1015,7 +1064,7 @@ assert(a != b); // -1 != 0 ``` You've probably noticed that Dart also contains -a `~/ `operator (called a _truncating division operator_), +a `~/` operator (called a _truncating division operator_), that divides a double and outputs a floored integer: {:.include-lang} @@ -1030,21 +1079,19 @@ assert(25 == 51.6 ~/ 2); The equality and relational operators of both languages work in the same way: -| Meaning | Dart operator | JS equivalent | -|-------------------------------|---------------|---------------| -| Strict equal | `==` | `===` | -| Abstract equal | | `==` | -| Strict not equal | `!=` | `!==` | -| Abstract not equal | | `!=` | -| Greater than | `>` | `>` | -| Less than | `<` | `<` | -| Greater than or equal to | `>=` | `>=` | -| Less than or equal to | `<=` | `<=` | +| Meaning | JavaScript operator | Dart operator | +|---------------------------|---------------------|---------------| +| Strict equal | `===` | `==` | +| Abstract equal | `==` | | +| Strict not equal | `!==` | `!=` | +| Abstract not equal | `!=` | | +| Greater than | `>` | `>` | +| Less than | `<` | `<` | +| Greater than or equal to | `>=` | `>=` | +| Less than or equal to | `<=` | `<=` | {:.table .table-striped} -Unlike JavaScript, -Dart doesn’t have the concept of abstract equality, -so the `==` and `!=` JavaScript operators have no equivalent. +The `==` and `!=` JavaScript operators have no equivalent. For example: @@ -1061,25 +1108,22 @@ assert(2 <= 3); #### Type test operators The implementation of test operators is a bit -different between the two languages: +different between the two languages: -| Meaning | Dart operator | JS equivalent | -|----------------------------------------------------|---------------|--------------------| -| Typecast (described below) | `var as T` | | -| True if the object has the specified type | `var is T` | `typeof var === T` | -| True if the object doesn’t have the specified type | `var is! T` | `typeof var !== T` | +| Meaning | JavaScript operator | Dart operator | +|-------------------------------------|---------------------|---------------| +| Typecast | | `x as T` | +| True if object has specified type | `x instanceof T` | `x is T` | +| True if object lacks specified type | `!(x instanceof T)` | `x is! T` | {:.table .table-striped} The result of `obj is T` is true if `obj` implements the interface specified by `T`. For example, `obj is Object?` is always true. -Since JavaScript makes use of type coercion, -it doesn't have an equivalent. - -Use the typecast operator to cast an object -to a particular type if—and only if—you -are sure that the object is of that type. +Use the typecast operator (`as`) to ensure that a value +has a particular type. The compiler can use that, +if you _know_ that the object will have that type. For example: @@ -1088,12 +1132,12 @@ For example: (person as Employee).employeeNumber = 4204583; ``` -If you aren't sure that the object is of type `T`, -then use `is T` to check the type before using the object. +If you don't _know_ that the object is of type `T`, +then use `is T` to check the type _before_ using the object. In Dart, the types of local variables update within the scope of the if statement. -This is not the case for instance variables. +This is not the case for instance variables. {:.include-lang} ```dart @@ -1108,22 +1152,22 @@ You can invert or combine boolean expressions using logical operators. The logical operators of both languages are identical. -|--------------------------------------------------------------------------+---------------+---------------| -| Meaning | Dart operator | JS equivalent | -|--------------------------------------------------------------------------|---------------|---------------| -| Inverts the following expression (changes false to true, and vice versa) | `!var` | `!var` | -| Logical OR | `||` | `||` | -| Logical AND | `&&` | `&&` | +|----------------------------------------------------------------+---------------------|---------------+ +| Meaning | JavaScript operator | Dart operator | +|----------------------------------------------------------------|---------------------|---------------| +| Inverts next expression (changes false to true and vice versa) | `!x` | `!x` | +| Logical OR | `||` | `||` | +| Logical AND | `&&` | `&&` | {:.table .table-striped} -Dart does not have the concept of "truthy" or "falsy" -values—only actual booleans. Because of this, -Logical OR and Logical AND expressions always resolve -to a boolean, not one of the two values like these -operators do in JavaScript. +JavaScript allows any value to be used where you need a Boolean value. +It then converts those values to either `true` or `false`. +JavaScript considers empty strings and the number `0` to be "falsy" values. +Dart allows `bool` values in conditions and as operands of logical operators. For example: +{:.include-lang} ```dart if (!done && (col == 0 || col == 3)) { // ...Do something... @@ -1137,19 +1181,19 @@ by using bitwise and shift operators with integers. The operators of both languages are almost identical, as shown in the following table: -|-------------------------------------------------------+---------------+---------------| -| Meaning | Dart operator | JS equivalent | -|-------------------------------------------------------|---------------|---------------| -| Bitwise AND | `&` | `&` | -| Bitwise OR | `|` | `|` | -| Bitwise XOR | `^` | `^` | -| Unary bitwise complement (0s become 1s; 1s become 0s) | `~expr` | `~expr` | -| Shift left | `<<` | `<<` | -| Shift right | `>>` | `>>` | -| Unsigned shift right | `>>>` | `>>>` | +|-------------------------------------------------------+---------------------+---------------| +| Meaning | JavaScript operator | Dart operator | +|-------------------------------------------------------|---------------------|---------------| +| Bitwise AND | `&` | `&` | +| Bitwise OR | `|` | `|` | +| Bitwise XOR | `^` | `^` | +| Unary bitwise complement (0s become 1s; 1s become 0s) | `~expr` | `~expr` | +| Shift left | `<<` | `<<` | +| Shift right | `>>` | `>>` | +| Unsigned shift right | `>>>` | `>>>` | {:.table .table-striped} -For example: +For example: {:.include-lang} ```dart @@ -1167,69 +1211,90 @@ assert((value >>> 4) == 0x02); // Unsigned shift right assert((-value >>> 4) > 0); // Unsigned shift right ``` -#### Ternary operator +#### Conditional operator -Both Dart and JavaScript contain a (`?:`) -ternary operator for evaluating expressions -that might otherwise require [if-else][] statements: +Both Dart and JavaScript contain a conditional operator (`?:`) +for evaluating expressions. +Some developers refer to this as a ternary operator +because it takes three operands. +As Dart has another operator (`[]=`) that takes three operands, +call this operator (`?:`) the conditional operator. +This operator works for expressions like [if-else][] does for statements. {:.include-lang} -```dart -final visibility = isPublic ? 'public' : 'private'; +```js +let visibility = isPublic ? "public" : "private"; ``` {:.include-lang} -```js -let visibility = isPublic ? "public" : "private"; +```dart +final visibility = isPublic ? 'public' : 'private'; ``` [if-else]: /guides/language/language-tour#if-and-else ### Assignment operators -As mentioned previously, -you can assign values using the (`=`) operator: +Use the (`=`) operator to assign values. +{:.include-lang} ```dart // Assign value to a a = value; ``` -This operator also has a null-aware variant. -For more information, -check out the [null-assignment](#null-aware-operators) operator section. +This operator also has a null-aware variant (`??=`). + +To learn more, +see the [null-assignment](#null-aware-operators) operator section. + +JavaScript and Dart include operators that calculate and assign +new values to the variable in the expression. +These assignment operators use the right-side value and +the variable initial value as operands. -Here are other assignment operators that directly -assign the result of an operation on a variable -back to that same variable: +The following table lists these assignment operators: -| `=` | `*=` | `%=` | `>>>=` | `^=` | -| `+=` | `/=` | `<<=` | `&=` | `|=` | -| `-=` | `~/=` | `>>=` | | | -{:.table} +| Operator | Description | ++----------+---------------------------------+ +| `=` | Assignment | +| `+=` | Addition assignment | +| `-=` | Subtraction assignment | +| `*=` | Multiplication assignment | +| `/=` | Division assignment | +| `~/=` | Truncating division assignment | +| `%=` | Remainder (modulo) assignment | +| `>>>=` | Unsigned right shift assignment | +| `^=` | Bitwise XOR assignment | +| `<<=` | Left shift assignment | +| `>>=` | Right shift assignment | +| `&=` | Bitwise AND assignment | +| `|=` | Bitwise OR assignment | +{:.table} + +JavaScript does not support the `~/=` assignment operator. {:.include-lang} ```dart var a = 5; -a *= 2; // Multiply `a` by 2 and assign the value back to a. +a *= 2; // Multiply `a` by 2 and assign the result back to a. print(a); // `a` is now 10. ``` -### Cascades (`..` operator) +### Cascades (`..` operator) + +Dart allows you to chain multiple method calls, property assignments, +or both on a single object. Dart refers to this as _cascading_ and +uses the cascade syntax (`..`) to perform this action. -Unlike JavaScript, -Dart supports cascading with the cascades operator. -This allows you to chain multiple method calls -or property assignments on a single object. +JavaScript lacks this syntax. -The following example shows setting the value -of multiple properties, then calling multiple methods -on a newly constructed object, all within a single chain -using the cascade operator: +The following example shows chaining multiple methods +on a newly constructed object using the cascade syntax: {:.include-lang} ```dart -var animal = Animal() +var animal = Animal() // Sets multiple properties and methods ..name = "Bob" ..age = 5 ..feed() @@ -1239,17 +1304,26 @@ print(animal.name); // "Bob" print(animal.age); // 5 ``` +To make the first cascade syntax null-aware, write it as `?..`. + +{:.include-lang} +```dart +var result = maybePerson + ?..employment = employer + ..salary = salary; +``` + +Dart ignores the entire cascade if the `maybePerson` value is `null`. + ## Collections -This section covers some collection types -in Dart and how they compare to their equivalents -in JavaScript. +This section covers some collection types in Dart and compare them +to similar types in JavaScript. ### Lists -List literals are defined the same way in Dart as -arrays are defined in JavaScript, -using square brackets and separated by commas: +Dart writes list literals in the same ways as JavaScript arrays. +Dart encloses lists in square brackets and separate values with commas. {:.include-lang} ```dart @@ -1263,10 +1337,10 @@ final list2 = ['one', 'two', 'three']; final list3 = ['one', 'two', 'three']; ``` -The following code samples give an overview of the -basic actions that you can perform on a Dart `List`. -The first example shows how to retrieve a value -from a `List` using the index operator: +The following code samples give an overview of the basic actions that +you can perform on a Dart `List`. +The following example shows how to retrieve a value from a `List` +using the index operator. {:.include-lang} ```dart @@ -1317,9 +1391,9 @@ fruits.removeLast(); fruits.removeAt(1); // Removes the elements with positions greater than // or equal to start (1) and less than end (3) from the list. -fruits.removeRange(1, 3); +fruits.removeRange(1, 3); // Removes all elements from the list that match the given predicate. -fruits.removeWhere((fruit) => fruit.contains('p')); +fruits.removeWhere((fruit) => fruit.contains('p')); ``` Use `length` to obtain the number of values in the `List`: @@ -1348,24 +1422,28 @@ assert(fruits.isNotEmpty); #### Filled -One handy feature of Dart's `List` class is the -`filled` constructor; use `filled` to quickly -create a list of size `n` with the specified default value. +Dart's `List` class includes a way to create a List with +each item having the same value. +This `filled` constructor creates a fixed-length list of size `n` with +one default value. The following example create a list of 3 items: {:.include-lang} ```dart -// Creates: [ 'a', 'a', 'a' ] -final list1 = List.filled(3, 'a'); +final list1 = List.filled(3, 'a'); // Creates: [ 'a', 'a', 'a' ] ``` +* You cannot add or remove elements from this list by default. + To permit this list to add or remove elements, add `, growable: true` + to the end of the parameter list. +* You can access and update elements of this list using their index value. + #### Generate -The `List` class also provides a `generate` -constructor to quickly create a list of -size `n` with a default value builder -that creates elements. -The value builder takes the index as a parameter. +The Dart `List` class includes a way to create a List of incrementing values. +This `generate` constructor creates a fixed-length list of size `n` +with a template to build element values. +This template takes the index as a parameter. {:.include-lang} ```dart @@ -1375,25 +1453,22 @@ final list1 = List.generate(3, (index) => 'a$index'); ### Sets -Unlike JavaScript, -Dart supports defining `Set`s with literals. -Sets are defined in the same way as lists, -but using curly braces instead of square brackets. -Sets are unordered collections that only contain -unique items. The uniqueness of these items are -enforced using hash codes, meaning that objects -need hash values to be stored in a `Set`. +Unlike JavaScript, Dart supports defining `Set`s with literals. +Dart defines sets in the same way as lists, +but using curly braces rather than square brackets. +Sets are unordered collections that only contain unique items. +Dart enforces the uniqueness of these items using hash codes, +meaning that objects need hash values to be stored in a `Set`. {{site.alert.note}} - In Dart, the hash value defaults to the - instance of an object but you can override - it to use a set of properties. For more information, - check out the [`hashCode`][] property page. + In Dart, the hash value defaults to the instance of an object + but you can override it to use a set of properties. + To learn more, see the [`hashCode`][] property page. {{site.alert.end}} [`hashCode`]: {{site.dart-api}}/dart-core/Object/hashCode.html -The following code snippet shows how to initialize a `Set`: +The following code snippet shows how to initialize a `Set`: {:.include-lang} ```dart @@ -1416,7 +1491,7 @@ final names = {}; The following examples provide an overview of the basic actions that you can perform on a Dart `Set`. -Add a value to the `Set` using the `add` method. +Add a value to the `Set` using the `add` method. Use the `addAll` method to add multiple values: {:.include-lang} @@ -1466,46 +1541,44 @@ assert(fruits.isNotEmpty); ### Maps -The `Map` type in Dart is similar to the `Map` type -in JavaScript. Both types associate keys with values. -A key can be any object type, so long as all keys have -the same type; the same is true for values. -Each key occurs once at most, but you can use the -same value multiple times. +The `Map` type in Dart resembles the `Map` type in JavaScript. +Both types associate keys with values. +A key can be any object type if all keys have the same type. +This rule applies to values as well. +Each key occurs once at most, but you can use the same value multiple times. -In Dart, the dictionary is based on a hash table, -which means that keys need to be hashable. In Dart, -every object contains a unique hash. +Dart bases the dictionary on a hash table. +This means that keys need to be hashable. +Every Dart object contains a hash. {{site.alert.note}} - In Dart, the hash value defaults to an instance - of an object but you can override it to resemble - a data class. For more information, - check out the [`hashCode`][] property page. +In Dart, the hash value of an object defaults to a value derived from +the object's identity, and being compatible with an equality where the +object can only equal itself. To introduce an equality based on the +_contents_ of the object, override `hashCode` and `operator==`. {{site.alert.end}} -Here are a couple of simple `Map` examples, -created using literals: +Consider these simple `Map` examples, created using literals: {:.include-lang} ```dart final gifts = { - 'first': 'partridge', - 'second': 'turtle doves', - 'fifth': 'golden rings' + 'first': 'partridge', + 'second': 'turtle doves', + 'fifth': 'golden rings' }; final nobleGases = { - 2: 'helium', - 10: 'neon', - 18: 'argon', + 2: 'helium', + 10: 'neon', + 18: 'argon', }; ``` -The following code samples provide an overview of the -basic actions that you can perform on a Dart `Map`. -The first example shows how to retrieve a value from -a `Map` using the index operator: +The following code samples provide an overview of the basic actions that +you can perform on a Dart `Map`. +The following example shows how to retrieve a value from a `Map` using +the index operator. {:.include-lang} ```dart @@ -1514,11 +1587,10 @@ final gift = gifts['first']; ``` {{site.alert.note}} - The index operator (`[]`) returns a **nullable** value. +If the map does not include the lookup key, the index operator returns `null`. {{site.alert.end}} -Use the `containsKey` method to check if a key -is already present in the `Map`: +Use the `containsKey` method to check if the `Map` includes a key. {:.include-lang} ```dart @@ -1526,11 +1598,10 @@ final gifts = {'first': 'partridge'}; assert(gifts.containsKey('fifth')); ``` -Use the index assignment operator (`[]=`) -to add or update an entry in the `Map`. -If the `Map` doesn't yet contain the key, -the entry is added; if the key is already present, -its value is updated. +Use the index assignment operator (`[]=`) to add or update an entry +in the `Map`. +If the `Map` doesn't yet contain the key, Dart adds the entry. +If the key exists, Dart updates its value. {:.include-lang} ```dart @@ -1539,26 +1610,25 @@ gifts['second'] = 'turtle'; // Gets added gifts['second'] = 'turtle doves'; // Gets updated ``` -Use the `addAll` method to add another `Map`; -use the `addEntries` method to add other entries to the `Map`: +Use the `addAll` method to add another `Map`. +Use the `addEntries` method to add other entries to the `Map`. {:.include-lang} ```dart final gifts = {'first': 'partridge'}; gifts['second'] = 'turtle doves'; gifts.addAll({ - 'second': 'turtle doves', - 'fifth': 'golden rings', + 'second': 'turtle doves', + 'fifth': 'golden rings', }); gifts.addEntries([ - MapEntry('second', 'turtle doves'), - MapEntry('fifth', 'golden rings'), + MapEntry('second', 'turtle doves'), + MapEntry('fifth', 'golden rings'), ]); ``` -Use the `remove` method to remove an entry from the `Map`; -remove all entries that satisfy a given test using the -`removeWhere` method: +Use the `remove` method to remove an entry from the `Map`. +Use the `removeWhere` method to remove all entries that satisfy a given test. {:.include-lang} ```dart @@ -1567,8 +1637,7 @@ gifts.remove('first'); gifts.removeWhere((key, value) => value == 'partridge'); ``` -Use `length` to obtain the number of key-value -pairs in the `Map`: +Use `length` to obtain the number of key-value pairs in the `Map`. {:.include-lang} ```dart @@ -1577,7 +1646,7 @@ gifts['fourth'] = 'calling birds'; assert(gifts.length == 2); ``` -Use `isEmpty` to check if the `Map` is empty: +Use `isEmpty` to check if the `Map` is empty. {:.include-lang} ```dart @@ -1585,7 +1654,7 @@ final gifts = {}; assert(gifts.isEmpty); ``` -Use `isNotEmpty` to check if the `Map` is not empty: +Use `isNotEmpty` to check if the `Map` is not empty. {:.include-lang} ```dart @@ -1595,9 +1664,9 @@ assert(gifts.isNotEmpty); ### Unmodifiable -Vanilla JavaScript doesn't support immutability. -Dart, however, offers multiple ways to make -collections like arrays, sets, or dictionaries immutable: +Pure JavaScript doesn't support immutability. +Dart offers multiple ways to make collections like arrays, sets, or +dictionaries immutable. * If the list is a compile-time constant and shouldn't be modified, use the `const` keyword:
    @@ -1611,7 +1680,7 @@ collections like arrays, sets, or dictionaries immutable: * Create a final version of your collection type using the `unmodifiable` constructor (as shown in the following example). - This creates a collection that cannot change its size or content: + This creates a collection that cannot change its size or content: {:.include-lang} ```dart @@ -1650,7 +1719,7 @@ var set2 = {'foo', 'baz', ...set1}; // {foo, baz, bar} ### Collection if/for In Dart, the `for` and `if` keywords have additional -functionality when it comes to collections. +functionality when it comes to collections. A collection `if` statement includes items from a list literal only when the specified condition is met: @@ -1694,31 +1763,35 @@ to their JavaScript counterparts. ### Futures -`Future` is Dart's version of a `Promise`: -an asynchronous operation that resolves at a later point. +`Future` is Dart's version of a JavaScript `Promise`. +Both are the _result_ of an asynchronous operation that resolves at a +later point. -Functions in Dart (or in packages that you use) might -return a `Future`, rather than the value they represent -directly, as the value might not be available until later. +Functions in Dart or in Dart packages might return a `Future`, +rather than the value they represent, as the value might not be +available until later. The following example shows that handling a future works -in the same way in Dart as a promise works in JavaScript: +in the same way in Dart as a promise works in JavaScript. {:.include-lang} -```dart -Future httpResponseBody = func(); +```js +const httpResponseBody = func(); -httpResponseBody.then((String value) { - print('Future resolved to a value: $value'); +httpResponseBody.then(value => { + console.log( + `Promise resolved to a value: ${value}` + ); }); ``` + {:.include-lang} -```js -const httpResponseBody = func(); +```dart +Future httpResponseBody = func(); -httpResponseBody.then(value => { - console.log(`Promise resolved to a value: ${value}`); +httpResponseBody.then((String value) { + print('Future resolved to a value: $value'); }); ``` @@ -1726,29 +1799,31 @@ Similarly, futures can fail like promises. Catching errors works the same as well: {:.include-lang} -```dart +```js httpResponseBody .then(...) - .catchError((err) { - print('Future encountered an error before resolving.'); + .catch(err => { + console.log( + "Promise encountered an error before resolving." + ); }); ``` {:.include-lang} -```js +```dart httpResponseBody .then(...) - .catch(err => { - console.log("Promise encountered an error before resolving."); + .catchError((err) { + print( + 'Future encountered an error before resolving.' + ); }); ``` -You can also create futures manually. -The easiest way to create a `Future` is by -defining and calling an `async` function, -which is discussed below. However, -when you have a value that needs to be a `Future`, -you can convert it as follows: +You can also create futures. +To create a `Future`, define and call an `async` function. +When you have a value that needs to be a `Future`, +convert the function as in the following example. {:.include-lang} ```dart @@ -1756,7 +1831,7 @@ String str = 'String Value'; Future strFuture = Future.value(str); ``` -#### Async/await +#### Async/Await If you're familiar with promises in JavaScript, you’re likely also familiar with the `async`/`await` syntax. @@ -1769,24 +1844,32 @@ it returns `Future`. The following example shows how to write an `async` function: -{:.include-lang} -```dart -// Returns a future of a string, as the method is async -Future fetchString() async { - // Typically some other async operations would be done here. - return 'String Value'; -} -``` {:.include-lang} ```js -// Returns a Promise of a string, as the method is async +// Returns a Promise of a string, +// as the method is async async fetchString() { - // Typically some other async operations would be done here. + // Typically some other async + // operations would be done here. return "String Value"; } ``` + +{:.include-lang} +```dart +// Returns a future of a string, +// as the method is async +Future fetchString() async { + // Typically some other async + // operations would be done here. + return 'String Value'; +} +``` + + + Call this `async` function as follows: {:.include-lang} @@ -1810,14 +1893,14 @@ The following example shows how to await a future for its value: {:.include-lang} ```dart // We can only await futures within an async context. -asyncFunction() async { +Future asyncFunction() async { var str = await fetchString(); print(str); // 'String Value' } ``` -For more information about `Future`s and the -`async`/`await` syntax, check out the +To learn more about `Future`s and the +`async`/`await` syntax, see the [Asynchronous programming][] codelab. [Asynchronous programming]: /codelabs/async-await @@ -1829,7 +1912,7 @@ While JavaScript has its own concept of streams, Dart's are more akin to `Observable`s, as found in the commonly used `rxjs` library. If you happen to be familiar with this library, -Dart's streams should feel familiar. +Dart's streams should feel familiar. For those not familiar with these concepts: `Stream`s basically act like `Future`s, @@ -1840,8 +1923,8 @@ and it can either complete or reach a fail state. #### Listening To listen to a stream, call its `listen` method -and provide a callback method. This method is -called whenever the stream emits a value: +and provide a callback method. Whenever the stream emits a value, +Dart calls this method: {:.include-lang} ```dart @@ -1851,7 +1934,7 @@ stream.listen((int value) { }); ``` -The `listen` method also has some optional callbacks +The `listen` method includes optional callbacks for handling errors or for when the stream completes: {:.include-lang} @@ -1897,8 +1980,8 @@ Future sumStream(Stream stream) async { When an error occurs when listening to a stream in this way, the error is rethrown at the line -containing the `await` keyword, -which you can handle with a `try-catch` statement: +containing the `await` keyword. +You can handle this error with a `try-catch` statement: {:.include-lang} ```dart @@ -1916,20 +1999,19 @@ you have several different ways to create a stream. The `Stream` class has utility constructors for creating streams from `Future`s or `Iterable`s, or for creating streams that emit values at a timed interval. -For more information, check out the [`Stream`][] API page. +To learn more, see the [`Stream`][] API page. [`Stream`]: {{site.dart-api}}/dart-async/Stream-class.html ##### StreamController -Another common way to create streams is -by using a [`StreamController`][], -a utility class that builds streams. -A `StreamController` contains a `stream` property -that exposes the stream it controls, -and multiple methods for controlling the stream, -such as emitting new items using the `add` method, -or completing the stream using the `close` method. +The utility class [`StreamController`][] can create and control streams. +Its stream property exposes the stream it controls. +Its methods provides ways to add events to that stream. + +For example, the `add` method can emit new items and the `close` method +completes the stream. + The following example shows basic usage of a stream controller: {:.include-lang} @@ -1956,11 +2038,9 @@ stream.listen((int value) { ##### Async generators -Another way to create streams is by using async generator -functions—these have the same syntax as a -synchronous generator function, but use the `async*` -keyword instead of `sync*`, -and always return a `Stream` instead of an `Iterable`. +Async generator functions can create streams. +These functions resemble a synchronous generator function +but use the `async*` keyword and return a `Stream`. In an async generator function, the `yield` keyword emits the given value to the stream. The `yield*` keyword, @@ -1976,10 +2056,10 @@ Stream asynchronousNaturalsTo(int n) async* { while (k < n) yield k++; } -Stream stream = asynchronousNaturalsTo(5); +Stream stream = asynchronousNaturalsTo(5); // Prints each of 0 1 2 3 4 in succession. -stream.listen((int value) => print(value)); +stream.forEach(print(value)); ``` Learn more about futures, streams, @@ -1988,14 +2068,14 @@ and other asynchronous functionality in the [asynchronous programming]: /tutorials/language/streams -## Classes +## Classes On the surface, classes in Dart are similar to classes in JavaScript, although JavaScript classes are technically more of a wrapper around prototypes. In Dart, classes are a standard feature of the language. This section covers defining and using classes in Dart -and how they differ from JavaScript. +and how they differ from JavaScript. ### “this” context @@ -2018,25 +2098,40 @@ a JavaScript constructor. In Dart, the `constructor` keyword is replaced by the full class name, and all parameters must be explicitly typed. In Dart, the `new` keyword was once required for creating class instances, -but is now optional and its use is no longer recommended. +but is now optional and its use is no longer recommended. {:.include-lang} ```dart class Point { - double x = 0; - double y = 0; + final double x; + final double y; - Point(double x, double y) { - // There's a better way to do this in Dart, stay tuned. - this.x = x; - this.y = y; - } + Point(double x, double y) : this.x = x, this.y = y { } } // Create a new instance of the Point class Point p = Point(3, 5); ``` +#### Initializer lists + +Use initializer lists to write your constructor. +Insert the initializer list between the constructor's parameters +and body. + +{:.include-lang} +```dart +class Point { + ... + Point.fromJson(Map json) + : x = json['x']!, + y = json['y']! { + print('In Point.fromJson(): ($x, $y)'); + } + ... +} +``` + #### Constructor parameters Writing code to assign class fields in the constructor @@ -2047,8 +2142,8 @@ so Dart has some syntactic sugar, called {:.include-lang} ```dart class Point { - double x = 0; - double y = 0; + double x; + double y; // Syntactic sugar for setting x and y // before the constructor body runs. @@ -2080,26 +2175,6 @@ class Point { } ``` -#### Initializer lists - -You can also use initializer lists, -which run after any fields that aren't set -using initializing parameters, -but run before the constructor body: - -{:.include-lang} -```dart -class Point { - ... - Point.fromJson(Map json) - : x = json['x']!, - y = json['y']! { - print('In Point.fromJson(): ($x, $y)'); - } - ... -} -``` - #### Named constructors Unlike JavaScript, Dart allows classes to have @@ -2127,10 +2202,8 @@ class Point { #### Const constructors -When your class instances are always immutable, -you can enforce this by using a `const` constructor. -Defining your constructor as `const` requires all -non-static fields in your class to be flagged as `final`: +To enable immutable class instances, use a `const` constructor. +A class with a `const` constructor can have `final` instance variables only. {:.include-lang} ```dart @@ -2143,9 +2216,8 @@ class ImmutablePoint { #### Constructor redirection -You can call constructors from other constructors, -for example to prevent code duplication or -to add additional defaults for parameters: +You can call constructors from other constructors to prevent code +duplication or to add additional defaults for parameters: {:.include-lang} ```dart @@ -2164,21 +2236,21 @@ class Point { You can use a factory constructor when you don't need to create a new class instance. -One example would be when returning a cached instance: +One example would be when returning a cached instance: {:.include-lang} ```dart class Logger { static final Map _cache = {}; - + final String name; - + // Factory constructor that returns a cached copy, // or creates a new one if it is not yet available. factory Logger(String name) { return _cache.putIfAbsent( - name, () => Logger._internal(name)); + name, () => _cache[name] ??= Logger._internal(name); } // Private constructor for internal use only @@ -2188,8 +2260,22 @@ class Logger { ### Methods -In both Dart and JavaScript, methods are -functions that provide behavior for an object. +In both Dart and JavaScript, methods serve as functions that provide +behavior for an object. + +{:.include-lang} +```js +function doSomething() { // This is a function + // Implementation.. +} + +class Example { + doSomething() { // This is a method + // Implementation.. + } +} +``` + {:.include-lang} ```dart @@ -2204,37 +2290,26 @@ class Example { } ``` -{:.include-lang} -```js -doSomething() { // This is a function - // Implementation.. -} -class Example { - doSomething() { // This is a method - // Implementation.. - } -} -``` ### Extending classes Dart allows classes to extend another class, -in the same way that JavaScript does. +in the same way that JavaScript does. {:.include-lang} ```dart class Animal { int eyes; - + Animal(this.eyes); - + makeNoise() { print('???'); } } class Cat extends Animal { - + Cat(): super(2); @override @@ -2252,7 +2327,7 @@ use the `@override` annotation. While this annotation is optional, it shows that the override is intentional. The Dart analyzer shows a warning if the method -is not actually overriding a superclass method. +is not actually overriding a superclass method. The parent method that is being overridden can still be called using the `super` keyword: @@ -2315,7 +2390,8 @@ class Cat implements Consumer { @override consume() { print('Eating mice...'); - super.consume(); // Invalid, because there’s no superclass. + super.consume(); + // Invalid. The superclass `Object` has no `consume` method. } } ``` @@ -2356,27 +2432,68 @@ consumer = Cat(); consumer.consume(); // Eating mice... ``` -### Mixins +### Mixins Mixins are used to share functionality between classes. You can use the mixin's fields and methods in the class, using their functionality as if it were part of the class. -A class can use multiple mixins, which is useful -when multiple classes share the same functionality, +A class can use multiple mixins. This helps when multiple classes share the +same functionality, without needing to inherit from each other or share a common ancestor. -A mixin is declared like a regular class, -as long as it doesn't extend any class other -than `Object` and has no constructors. -Use the `with` keyword to add one or more -comma-separated mixins to a class. -Although JavaScript doesn’t have an equivalent -for this keyword, the effect is similar to using -`Object.assign` to merge additional objects into -an existing object, after instantiating. +Use the `with` keyword to add one or more comma-separated mixins to a class. + +JavaScript has no keyword equivalent. JavaScript can use `Object.assign` +to merge additional objects into an existing object, after instantiating. + +The following examples show how JavaScript and Dart achieve similar behavior: + + +{:.include-lang} +```js +class Animal {} + +// Defining the mixins +class Flyer { + fly = () => console.log('Flaps wings'); +} +class Walker { + walk = () => console.log('Walks on legs'); +} + +class Bat extends Animal {} +class Goose extends Animal {} +class Dog extends Animal {} + +// Composing the class instances with +// their correct functionality. +const bat = + Object.assign( + new Bat(), + new Flyer() + ); +const goose = + Object.assign( + new Goose(), + new Flyer(), + new Walker() + ); +const dog = + Object.assign( + new Dog(), + new Walker() + ); + +// Correct calls +bat.fly(); +goose.fly(); +goose.walk(); +dog.walk(); +// Incorrect calls +bat.walk(); // `bat` lacks the `walk` method +dog.fly(); // `dog` lacks the `fly` method +``` -The following example shows how similar behavior -is replicated in JavaScript and how it's achieved in Dart: {:.include-lang} ```dart @@ -2387,9 +2504,9 @@ class Flyer { fly() => print('Flaps wings'); } class Walker { - walk() => print('Walks legs'); + walk() => print('Walks on legs'); } - + class Bat extends Animal with Flyer {} class Goose extends Animal with Flyer, Walker {} class Dog extends Animal with Walker {} @@ -2397,43 +2514,14 @@ class Dog extends Animal with Walker {} // Correct calls Bat().fly(); Goose().fly(); -Goose().walk(); +Goose().walk(); Dog().walk(); // Incorrect calls Bat().walk(); // Not using the Walker mixin Dog().fly(); // Not using the Flyer mixin ``` -{:.include-lang} -```js -class Animal {} -// Defining the mixins -class Flyer { - fly = () => console.log('Flaps wings'); -} -class Walker { - walk = () => console.log('Walks legs'); -} - -class Bat extends Animal {} -class Goose extends Animal {} -class Dog extends Animal {} - -// Composing the class instances with their correct functionality. -const bat = Object.assign(new Bat(), new Flyer()); -const goose = Object.assign(new Goose(), new Flyer(), new Walker()); -const dog = Object.assign(new Dog(), new Walker()); - -// Correct calls -bat.fly(); -goose.fly(); -goose.walk(); -dog.walk(); -// Incorrect calls -bat.walk(); // `bat` does not have the `walk` method -dog.fly(); // `dog` does not have the `fly` method -``` Alternatively, you can replace the `class` keyword with `mixin` to prevent the mixin from being used @@ -2453,7 +2541,7 @@ they can have overlapping methods or fields with each other when used on the same class. They can even overlap with the class that uses them, or that class's superclass. -The order in which they are added to a class matters. +The order in which they are added to a class matters. To give an example: @@ -2478,7 +2566,7 @@ However, sometimes it's useful to extend a class that already exists or is part of another library or the Dart SDK. In these cases, Dart offers the ability to write extensions -for existing classes. +for existing classes. As an example, the following extension on the `String` class from the Dart SDK allows parsing of integers: @@ -2509,6 +2597,7 @@ var age = '42'.parseInt(); // Use the extension method. Getters and setters in Dart work exactly like their JavaScript counterparts: + {:.include-lang} ```js class Person { @@ -2520,7 +2609,9 @@ class Person { set age(value) { if (value < 0) { - throw new Error('age cannot be negative'); + throw new Error( + 'age cannot be negative' + ); } this._age = value; } @@ -2531,18 +2622,21 @@ person.age = 10; console.log(person.age); ``` + {:.include-lang} ```dart class Person { int _age = 0; - + int get age { return _age; } - + set age(int value) { if (value < 0) { - throw ArgumentError('Age cannot be negative'); + throw ArgumentError( + 'Age cannot be negative' + ); } _age = value; } @@ -2555,26 +2649,25 @@ void main() { } ``` + + ### Public and private members Like JavaScript, Dart has no access modifier keywords: -all class members are public by default. +all class members are public by default. -While private class members are not yet officially -part of JavaScript because they are not part of any -published EcmaScript standard, -a proposal for this has been completed and is ready -to be included in the next publication of the standard. +JavaScript will include private class members in the next +practical revision of the EcmaScript standard. As such, implementations for this have been available in -various browsers and runtimes for a while already. +various browsers and runtimes for some time. -In JavaScript, you can indicate that a class member is private -by adding a pound symbol (`#`) as a prefix to its name: +To make a class member private in JavaScript, +prefix its name with a pound (or hash) symbol (`#`). {:.include-lang} ```js class Animal { - eyes; // Public field + eyes; // Public field #paws; // Private field #printEyes() { // Private method @@ -2587,14 +2680,13 @@ class Animal { } ``` -Similarly, Dart allows developers to make a -class member private by prefixing its name -with an underscore (`_`): +To make a class member private in Dart, prefix its name +with an underscore (`_`). {:.include-lang} ```dart class Animal { - int eyes; // Public field + int eyes; // Public field int _paws; // Private field void _printEyes() { // Private method @@ -2607,113 +2699,87 @@ class Animal { } ``` -In JavaScript, this is a convention, -but in Dart this is a full language feature -enforced by the compiler. +JavaScript uses the hash as a convention. +Dart's compiler enforces use of the underscore for this feature. -A difference that should be noted is that in Dart, -private members are not private to the class, -but are private to the library, -meaning that private members can still be accessed -from code that is considered part of the same library. -By default, this is possible anywhere in the same file, -so private class members can still be accessed from code -in the same file. While you can expand this library scope -beyond a single file using the `part` directive, -it's generally advised to [avoid doing so][] and is usually -reserved for code generators. +Dart makes private members private to the library, not the class. +This means that you can access private members from code in the same library. +By default, Dart limits access to private class members to code in the same file. +To expand the scope of a library beyond one file, add the `part` directive. +When possible, [avoid using `part`][]. Reserve using `part` for code generators. -[avoid doing so]: /guides/libraries/create-library-packages#organizing-a-library-package +[avoid using `part`]: /guides/libraries/create-library-packages#organizing-a-library-package ### Late variables -Assign the `late` keyword to class fields to -indicate they are initialized at a later point, -while remaining non-nullable. This is useful -for cases where a variable is never observed -before being initialized, allowing it to be initialized later. -This has several advantages over just labeling the field as nullable: +To indicate that Dart initializes class fields at a later point, +assign the `late` keyword to those class fields. +Those class fields remain non-nullable. +Do this when a variable doesn't need to observed or accessed immediately +and can be initialized later. +This differs from labeling the field as nullable. * (Non-nullable) late fields cannot have null assigned at a later point. * (Non-nullable) late fields throw a runtime error when - accessed before they are initialized. + accessed before they initialize. This should be avoided. {:.include-lang} ```dart -// Using null safety: -class Coffee { - late String _temperature; - - void heat() { _temperature = 'hot'; } - void chill() { _temperature = 'iced'; } - - String serve() => _temperature + ' coffee'; +class PetOwner { + final String name; + late final Pet _pet; + PetOwner(this.name, String petName) { + // Cyclic object graph, cannot set _pet before owner exists. + _pet = Pet(petName, this); + } + Pet get pet => _pet; +} +class Pet { + final String name; + final PetOwner owner; + Pet(this.name, this.owner); } ``` -In this case, `_temperature` is only initialized -after calling `heat()` or `chill()`. -If `serve()` is called before either are called, -a runtime exception occurs. -The `_temperature` field can never be assigned `null`. - -You can use the `late` keyword to make initialization _lazy_, -when combined with an initializer: +Use `late` for local variables only if unclear code results +in the compiler being unable determine if the code initialized the variable. {:.include-lang} ```dart -class Weather { - late int _temperature = _readThermometer(); +doSomething(int n, bool capture) { + late List captures; + if (capture) captures = []; + for (var i = 0; i < n; i++) { + var foo = something(i); + if (capture) captures.add(foo); + } } ``` -In this example, `_readThermometer()` only runs -when the field is first accessed, -rather than on initialization. - -Lastly, use the `late` keyword to delay initialization -of `final` variables. While you don't need to immediately -initialize the final variable when marking it as `late`, -it still allows the variable to be initialized only once. -A second assignment results in a runtime error. - -{:.include-lang} -```dart -late final int a; -a = 1; -a = 2; // Throws a runtime exception `a` is already initialized. -``` +In the preceding example, the compiler does not know to assign +`captures` if `capture` is true. Using `late` delays the normal +"assigned" checks until runtime. -## Generics +## Generics -While Vanilla JavaScript doesn’t offer generics, -they are available in Dart to improve type safety -and reduce code duplication. +While JavaScript doesn’t offer generics, +Dart does to improve type safety and reduce code duplication. -### Generic methods +### Generic methods You can apply generics to methods. -To define a generic type, place it between `< >` -symbols after the method name. -This type can then be used within the method -(as the return type), or within the method’s parameters: +To define a generic type parameter, place it between angle brackets `< >` +after the method name. +You can then use this type within the method +as the return type or within the method’s parameters: {:.include-lang} ```dart -// Defining a method that uses generics. -T transform(T param) { - // E.g. doing some transformation on `param`... - return param; -} -// Calling the method. Variable `str` is of type String. -var str = transform('string value'); +Map _cache = {}; +T cache(T value) => (_cache[value] ??= value) as T; ``` -In this case, passing `String` to the `transform` method -ensures that it returns a `String`. Likewise, -if an `int` is provided, the return value is an `int`. - Define multiple generic types by separating them with a comma: {:.include-lang} @@ -2731,11 +2797,10 @@ transform(5, 'string value'); ### Generic classes Generics can also be applied to classes. -You can include the type to use when calling a constructor, -which allows you to tailor reusable classes to specific types. +You can include the type to use when calling a constructor. +This allows you to tailor reusable classes to specific types. -In the following example, the `Cache` class is for -caching specific types: +In the following example, the `Cache` class caches specific types: {:.include-lang} ```dart @@ -2749,8 +2814,8 @@ stringCache.setByKey('Foo', 'Bar'); // Valid, setting a string value. stringCache.setByKey('Baz', 5); // Invalid, int type does not match generic. ``` -If the type declaration is omitted, -the runtime type will be `Cache` +If you omit the type declaration, +the runtime type becomes `Cache` and both calls to `setByKey` are valid. ### Restricting generics @@ -2766,20 +2831,19 @@ class NumberManager { ... } // Valid. -var manager = NumberManager(); -var manager = NumberManager(); +var manager = NumberManager(); +var manager = NumberManager(); // Invalid, String nor its parent classes extend num. -var manager = NumberManager(); +var manager = NumberManager(); ``` ### Generics in literals -`Map`, `Set`, and `List` literals can explicitly -declare generic types, which is useful when the -type isn’t inferred or is incorrectly inferred. +`Map`, `Set`, and `List` literals can accept type arguments. +This helps when Dart cannot infer the type or infer the type correctly. For example, the `List` class has a generic definition: -`class List`. Generic type `E` refers to the type of +`class List`. The type parameter `E` refers to the type of the list’s contents. Normally, this type is automatically inferred, which is used in some `List` class’s member types. (For example, its first getter returns a value of type `E`.) @@ -2842,13 +2906,13 @@ int get length => ... This guide has introduced you to the major differences between Dart and JavaScript. At this point, -you might consider moving to the general documentation -for Dart or [Flutter]({{site.flutter}}) -(an open-source framework that -uses Dart for building beautiful, natively compiled, -multi-platform applications from a single codebase), -where you'll find in-depth information about the -language and practical ways of getting started. +consider reading the Dart documentation. +You could also read the [Flutter]({{site.flutter}}) docs. +Built with Dart, Flutter is an open-source framework that +uses Dart for building natively compiled, +multi-platform applications from a single codebase. +These docs provide in-depth information about the +language and practical ways of getting started. Some possible next steps: From 0099ada4bba59142788041867e3088bb54d3114b Mon Sep 17 00:00:00 2001 From: Parker Lougheed Date: Mon, 21 Nov 2022 11:45:51 -0600 Subject: [PATCH 27/32] Provide better clarity around operator precedence and associativity (#4332) While the precedence outlined by the table should only be used as a guideline, users are instead finding third-party sources when googling which do not highlight potential issues and are not able to identify/search that this table still approximates the behavior even if they navigate to the language tour. This PR makes the table more searchable and identifiable as outlining the approximate precedence, while also clarifying the warning which was a bit confusing, focusing on that it can just be used as a "helpful guide". Beyond that, this adds the associativity labels present on the language spec's "helpful guide". Fixes #4287 **Staged:** https://dart-dev--pr4332-feature-document-ass-ys8cfbyn.web.app/guides/language/language-tour#operators Co-authored-by: Anthony Sansone --- src/_guides/language/language-tour.md | 50 +++++++++++++++------------ 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/src/_guides/language/language-tour.md b/src/_guides/language/language-tour.md index 47b4f8b48..5f763f800 100644 --- a/src/_guides/language/language-tour.md +++ b/src/_guides/language/language-tour.md @@ -1688,33 +1688,38 @@ assert(foo() == null); ## Operators Dart supports the operators shown in the following table. +The table shows Dart's operator associativity +and [operator precedence](#operator-precedence-example) from highest to lowest, +which are an **approximation** of Dart's operator relationships. You can implement many of these [operators as class members](#_operators). -|--------------------------+------------------------------------------------| -|Description | Operator | -|--------------------------|------------------------------------------------| -| unary postfix | expr++    expr--    `()`    `[]`    `?[]`    `.`    `?.`    `!` | -| unary prefix | -expr    !expr    ~expr    ++expr    --expr      await expr    | -| multiplicative | `*`    `/`    `%`  `~/` | -| additive | `+`    `-` | -| shift | `<<`    `>>`    `>>>` | -| bitwise AND | `&` | -| bitwise XOR | `^` | -| bitwise OR | `|` | -| relational and type test | `>=`    `>`    `<=`    `<`    `as`    `is`    `is!` | -| equality | `==`    `!=`    | -| logical AND | `&&` | -| logical OR | `||` | -| if null | `??` | -| conditional | expr1 ? expr2 : expr3 | -| cascade | `..`    `?..` | -| assignment | `=`    `*=`    `/=`   `+=`   `-=`   `&=`   `^=`   etc. | +|-----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------| +| Description | Operator | Associativity | +|-----------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------| +| unary postfix | expr++    expr--    `()`    `[]`    `?[]`    `.`    `?.`    `!` | None | +| unary prefix | -expr    !expr    ~expr    ++expr    --expr      await expr    | None | +| multiplicative | `*`    `/`    `%`  `~/` | Left | +| additive | `+`    `-` | Left | +| shift | `<<`    `>>`    `>>>` | Left | +| bitwise AND | `&` | Left | +| bitwise XOR | `^` | Left | +| bitwise OR | `|` | Left | +| relational and type test | `>=`    `>`    `<=`    `<`    `as`    `is`    `is!` | None | +| equality | `==`    `!=`    | None | +| logical AND | `&&` | Left | +| logical OR | `||` | Left | +| if null | `??` | Left | +| conditional | expr1 ? expr2 : expr3 | Right | +| cascade | `..`    `?..` | Right | +| assignment | `=`    `*=`    `/=`   `+=`   `-=`   `&=`   `^=`   etc. | Right | {:.table .table-striped} {{site.alert.warning}} - Operator precedence is an approximation of the behavior of a Dart parser. - For definitive answers, consult the grammar in the - [Dart language specification][]. + The previous table should only be used as a helpful guide. + The notion of operator precedence and associativity + is an approximation of the truth found in the language grammar. + You can find the authoritative behavior of Dart's operator relationships + in the grammar defined in the [Dart language specification][]. {{site.alert.end}} When you use operators, you create expressions. Here are some examples @@ -1730,6 +1735,7 @@ c ? a : b a is T ``` + In the [operator table](#operators), each operator has higher precedence than the operators in the rows that follow it. For example, the multiplicative operator `%` has higher From f40cec22c88c21e0f42eceb0f5ea77d1b43f09ac Mon Sep 17 00:00:00 2001 From: Luke Cheng <2258420+chenglu@users.noreply.github.com> Date: Mon, 28 Nov 2022 03:59:15 +0000 Subject: [PATCH 28/32] submodule sync --- site-shared | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site-shared b/site-shared index 3f55d0770..61dcf5820 160000 --- a/site-shared +++ b/site-shared @@ -1 +1 @@ -Subproject commit 3f55d07704b43696ee36ac281a364d4f3faa19d2 +Subproject commit 61dcf58208e249511261ec796c4005a8f4e049b2 From 04d87e5c56cad9d6a72702da3e137c7920878fa1 Mon Sep 17 00:00:00 2001 From: Luke Cheng <2258420+chenglu@users.noreply.github.com> Date: Mon, 28 Nov 2022 07:26:54 +0000 Subject: [PATCH 29/32] remove dart-io.md --- src/_articles/libraries/dart-io.md | 389 ----------------------------- 1 file changed, 389 deletions(-) delete mode 100644 src/_articles/libraries/dart-io.md diff --git a/src/_articles/libraries/dart-io.md b/src/_articles/libraries/dart-io.md deleted file mode 100644 index 20b38449e..000000000 --- a/src/_articles/libraries/dart-io.md +++ /dev/null @@ -1,389 +0,0 @@ ---- -title: "An introduction to the dart:io library" -title: "介绍 dart:io 库的使用方式" -description: An introduction to the Dart I/O library, which is aimed at code that runs in Flutter and the standalone Dart VM. -description: 介绍 Dart 的输入和输出库。 -original-date: 2012-03-01 -date: 2021-06-03 -category: libraries ---- - -_Written by Mads Ager
    -March 2012 (updated June 2021)_ - -The [dart:io]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-io/dart-io-library.html) library -is aimed at code that runs in Flutter and the standalone Dart VM. -In this article we will give you a feel for -what is currently possible with dart:io -by going through a couple of examples. - -{{site.alert.note}} - When writing a Flutter app, use - [Flutter-specific APIs]({{site.flutter-api}}) - instead of dart:io whenever possible. For example, use the - [Flutter asset support]({{site.flutter-docs}}/development/ui/assets-and-images) to load - images and other assets into your app. -{{site.alert.end}} - -Dart is a single-threaded programming language. -If an operation blocks the Dart thread, -the application makes no progress before that operation completes. -For scalability it is therefore crucial that no I/O operations block. -Instead of blocking on I/O operations, -dart:io uses an asynchronous programming model inspired by -[node.js,](https://nodejs.org) -[EventMachine,](https://github.com/eventmachine/eventmachine/wiki) and -[Twisted.](https://twisted.org/) - -## The Dart VM and the event loop - -Before we dive into asynchronous I/O operations, -it might be useful to explain how the standalone Dart VM operates. - -When executing a server-side application, -the Dart VM runs in an event loop with -an associated event queue of pending asynchronous operations. -The VM terminates when it has executed the current code to completion -and no more pending operations are in the queue. - -One simple way to add an event to the event queue is to -schedule a function to be called in the future. -You can do this by creating a -[Timer]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-async/Timer-class.html) object. -The following example registers a timer with the event queue -and then drops off the end of `main()`. -Because a pending operation is in the event queue, -the VM does not terminate at that point. -After one second, -the timer fires and the code in the argument callback executes. -Once that code executes to completion, -no more pending operations are in the event queue -and the VM terminates. - - -```dart -import 'dart:async'; - -void main() { - Timer(const Duration(seconds: 1), () => print('timer')); - print('end of main'); -} -``` - -Running this example at the command line, we get: - -```terminal -$ dart run timer.dart -end of main -timer -``` - -Had we made the timer repeating by using the -[Timer.periodic]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-async/Timer/Timer.periodic.html) constructor, -the VM would not terminate -and would continue to print out 'timer' every second. - -## File system access - -The dart:io library provides access to files and directories through the -[File]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-io/File-class.html) and -[Directory]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-io/Directory-class.html) classes. - -The following example prints its own source code. -To determine the location of the source code being executed, -we use the -[Platform]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-io/Platform-class.html) -class. - - - -```dart -import 'dart:convert'; -import 'dart:io'; - -void main() async { - var file = File(Platform.script.toFilePath()); - print(await (file.readAsString(encoding: ascii))); -} -``` - -Notice that the `readAsString()` method is asynchronous; -it returns a [Future]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-async/Future-class.html) -that returns the contents of the file -once the file has been read from the underlying system. -This asynchronicity allows the Dart thread to perform other work -while waiting for the I/O operation to complete. - -To illustrate more detailed file operations, -let's change the example to read the contents -only up to the first semicolon and then to print that. -You could do this in two ways: -either open the file for random access, -or open a -[Stream]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-async/Stream-class.html) -for the file and stream in the data. - -Here is a version that opens the file for random access operations. -The code opens the file for reading and then reads one byte at a time -until it encounters the char code for `;`. - - -```dart -import 'dart:io'; - -void main() async { - final semicolon = ';'.codeUnitAt(0); - final result = []; - - final script = File(Platform.script.toFilePath()); - RandomAccessFile file = await script.open(mode: FileMode.read); - - // Deal with each byte. - while (true) { - final byte = await file.readByte(); - result.add(byte); - if (byte == semicolon) { - print(String.fromCharCodes(result)); - await file.close(); - break; - } - } -} -``` - -When you see a use of `async` or `await`, you are seeing a Future in action. -Both the `open()` and `readByte()` methods return a Future object. - -This code is, of course, -a very simple use of random-access operations. -Operations are available for writing, -seeking to a given position, truncating, and so on. - -Let's implement a version using a stream. -The following code opens the file for reading presenting the content -as a stream of lists of bytes. Like all streams in Dart you listen on -this stream (using `await for`) and the data is given in chunks. - - -```dart -import 'dart:io'; - -void main() async { - final result = []; - - Stream> stream = File(Platform.script.toFilePath()).openRead(); - final semicolon = ';'.codeUnitAt(0); - - await for (final data in stream) { - for (int i = 0; i < data.length; i++) { - result.add(data[i]); - if (data[i] == semicolon) { - print(String.fromCharCodes(result)); - return; - } - } - } -} -``` - -The stream subscription is implicitly handled by `await for`. -Exiting the `await for` statement—using `break`, `return`, -or an uncaught exception—cancels the subscription. - -`Stream>` is used in multiple places in dart:io: -when working with stdin, files, sockets, HTTP connections, and so on. -Similarly, [IOSink]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-io/IOSink-class.html) objects -are used to stream data to -stdout, files, sockets, HTTP connections, and so on. - -## Interacting with processes - -For the simple case, use -[Process.run()]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-io/Process/run.html) -to run a process -and collect its output. Use `run()` when you don't -need interactive control over the process. - - -```dart -import 'dart:io'; - -void main() async { - // List all files in the current directory, - // in UNIX-like operating systems. - ProcessResult results = await Process.run('ls', ['-l']); - print(results.stdout); -} -``` - -You can also start a process by creating a -[Process]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-io/Process-class.html) object -using -[Process.start().]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-io/Process/start.html) - -Once you have a Process object you can interact with the process -by writing data to its stdin sink, -reading data from its stderr and stdout streams, -and killing the process. -When the process exits, the `exitCode` future completes with -the exit code of the process. - -The following example runs `ls -l` in a separate process -and prints the output and the exit code for the process to stdout. -Since we are interested in getting lines, -we use a -[Utf8Decoder]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-convert/Utf8Decoder-class.html) -(which decodes chunks of bytes into strings) followed by a -[LineSplitter]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-convert/LineSplitter-class.html) -(which splits the strings at line boundaries). - - -```dart -import 'dart:convert'; -import 'dart:io'; - -void main() async { - final process = await Process.start('ls', ['-l']); - final lineStream = process.stdout - .transform(const Utf8Decoder()) - .transform(const LineSplitter()); - - await for (final line in lineStream) { - print(line); - } - - await process.stderr.drain(); - print('exit code: ${await process.exitCode}'); -} -``` - -Notice that `exitCode` can complete before all of the lines of output -have been processed. Also note -that we do not explicitly close the process. In order to -not leak resources we have to listen to both the stderr and stdout -streams. We use `await for` to listen to stdout, -and `stderr.drain()` to listen to (and discard) stderr. - -Instead of printing the output to stdout, -we can use the streaming classes -to pipe the output of the process to a file. - - -```dart -import 'dart:io'; - -void main() async { - final output = File('output.txt').openWrite(); - Process process = await Process.start('ls', ['-l']); - - // Wait for the process to finish; get the exit code. - final exitCode = (await Future.wait([ - process.stdout.pipe(output), // Send stdout to file. - process.stderr.drain(), // Discard stderr. - process.exitCode - ]))[2]; - - print('exit code: $exitCode'); -} -``` - - -## Writing web servers - -dart:io makes it easy to write HTTP servers and clients. -To write a simple web server, -all you have to do is create an -[HttpServer]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-io/HttpServer-class.html) -and hook up a listener (using `await for`) to its stream of `HttpRequest`s. - -Here is a simple web server -that just answers 'Hello, world' to any request. - - -```dart -import 'dart:io'; - -void main() async { - final server = await HttpServer.bind('127.0.0.1', 8082); - await for (final request in server) { - request.response.write('Hello, world'); - await request.response.close(); - } -} -``` - -Running this application -and pointing your browser to 'http://127.0.0.1:8082' -gives you 'Hello, world' as expected. - -Let's add a bit more and actually serve files. -The base path for every file that we serve will be -the location of the script. -If no path is specified in a request we will serve index.html. -For a request with a path, -we will attempt to find the file and serve it. -If the file is not found we will respond with a '404 Not Found' status. -We make use of the streaming interface -to pipe all the data read from a file directly to the response stream. - -```dart -import 'dart:io'; - -Future runServer(String basePath) async { - final server = await HttpServer.bind('127.0.0.1', 8082); - await for (final request in server) { - await handleRequest(basePath, request); - } -} - -Future handleRequest(String basePath, HttpRequest request) async { - final String path = request.uri.toFilePath(); - // PENDING: Do more security checks here. - final String resultPath = path == '/' ? '/index.html' : path; - final File file = File('$basePath$resultPath'); - if (await file.exists()) { - try { - await request.response.addStream(file.openRead()); - } catch (exception) { - print('Error happened: $exception'); - await sendInternalError(request.response); - } - } else { - await sendNotFound(request.response); - } -} - -Future sendInternalError(HttpResponse response) async { - response.statusCode = HttpStatus.internalServerError; - await response.close(); -} - -Future sendNotFound(HttpResponse response) async { - response.statusCode = HttpStatus.notFound; - await response.close(); -} - -void main() async { - // Compute base path for the request based on the location of the - // script, and then start the server. - final script = File(Platform.script.toFilePath()); - await runServer(script.parent.path); -} -``` - -Writing HTTP clients is very similar to using the -[HttpClient]({{site.dart-api}}/{{site.data.pkg-vers.SDK.channel}}/dart-io/HttpClient-class.html) -class. - - -## Feature requests welcome - -The dart:io library is already capable of performing a lot of tasks. -For example, the [pub.dev site]({{site.pub}}) uses dart:io. - -Please give dart:io a spin and let us know what you think. -Feature requests are very welcome! -When you file a bug or feature request, -use [dartbug.com.](https://dartbug.com) -To find reported issues, search for the -[library-io label.](https://github.com/dart-lang/sdk/issues?q=label%3Alibrary-io) From 749f472d6935c6596914f2c24570ab961b493b3f Mon Sep 17 00:00:00 2001 From: Luke Cheng <2258420+chenglu@users.noreply.github.com> Date: Thu, 1 Dec 2022 21:44:28 +0800 Subject: [PATCH 30/32] Apply suggestions from code review Co-authored-by: Alex Li --- src/_guides/language/language-tour.md | 6 ++++++ src/null-safety/faq.md | 3 +++ src/tools/pub/cmd/pub-global.md | 3 +++ 3 files changed, 12 insertions(+) diff --git a/src/_guides/language/language-tour.md b/src/_guides/language/language-tour.md index c972e5d24..00ece9f8b 100644 --- a/src/_guides/language/language-tour.md +++ b/src/_guides/language/language-tour.md @@ -1894,6 +1894,9 @@ use `=` to specify a default value. The specified value must be a compile-time constant. For example: +你可以使用 `=` 来为一个命名参数指定除了 `null` 以外的默认值。 +指定的默认值必须要为编译时的常量,例如: + ```dart /// Sets the [bold] and [hidden] flags ... @@ -1907,6 +1910,9 @@ If you instead want a named parameter to be mandatory, requiring callers to provide a value for the parameter, annotate them with `required`: +如果你希望一个命名参数是强制需要使用的,调用者需要提供它的值, +则你可以使用 `required` 进行声明: + ```dart const Scrollbar({super.key, [!required!] Widget child}); diff --git a/src/null-safety/faq.md b/src/null-safety/faq.md index bec3f9e32..0d41430e6 100644 --- a/src/null-safety/faq.md +++ b/src/null-safety/faq.md @@ -451,6 +451,9 @@ To generate a fixed-length list, use the [`List.generate`][] constructor with the `growable` parameter set to `false`: +你可以使用 [`List.generate`][] 构造加 +`growable` 参数设置为 `false` 来生成固定长度的列表: + ```dart _jellyPoints = List.generate(jellyMax, (_) => Vec2D(), growable: false); ``` diff --git a/src/tools/pub/cmd/pub-global.md b/src/tools/pub/cmd/pub-global.md index ba7a80c55..061e50ee3 100644 --- a/src/tools/pub/cmd/pub-global.md +++ b/src/tools/pub/cmd/pub-global.md @@ -108,6 +108,9 @@ To specify a different location, use the `--git-path` option with a path relative to the repository root: +Pub 会尝试在 Git 仓库的根目录寻找 package。 +你可以使用 `--git-path` 选项为 Pub 指定用于查找的相对于仓库的路径: + ```terminal $ dart pub global activate -sgit https://github.com/dart-lang/http.git --git-path pkgs/http/ ``` From 73be28dbdc2db4907833de34b21b4410a17733ea Mon Sep 17 00:00:00 2001 From: Luke Cheng <2258420+chenglu@users.noreply.github.com> Date: Thu, 1 Dec 2022 21:45:02 +0800 Subject: [PATCH 31/32] Update src/_guides/language/language-tour.md Co-authored-by: Alex Li --- src/_guides/language/language-tour.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/_guides/language/language-tour.md b/src/_guides/language/language-tour.md index 00ece9f8b..ce3cce31c 100644 --- a/src/_guides/language/language-tour.md +++ b/src/_guides/language/language-tour.md @@ -1997,9 +1997,8 @@ use `=` to specify a default value. The specified value must be a compile-time constant. For example: -若为除了 `null` 以外的可选位置参数提供一个默认值的话,需要使用 `=` 来定义。 -设定的这个值必须是一个编译时的常量。 -例如: +你可以使用 `=` 来为一个位置可选参数指定除了 `null` 以外的默认值。 +指定的默认值必须要为编译时的常量,例如: ```dart From 59764a47336af9534f4bf8339e54309a6648bd52 Mon Sep 17 00:00:00 2001 From: Luke Cheng <2258420+chenglu@users.noreply.github.com> Date: Sat, 3 Dec 2022 16:02:43 +0000 Subject: [PATCH 32/32] Add missed English translation --- src/_guides/language/language-tour.md | 11 +++++++++++ src/null-safety/migration-guide.md | 3 ++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/_guides/language/language-tour.md b/src/_guides/language/language-tour.md index ce3cce31c..13532909d 100644 --- a/src/_guides/language/language-tour.md +++ b/src/_guides/language/language-tour.md @@ -1868,6 +1868,10 @@ as their default value will be `null`: 定义函数时,使用 {参数1, 参数2, …} 来指定命名参数: +如果你没有提供一个默认值, +也没有使用 `required` 标记的话, +那么它一定可空的类型, +因为他们的默认值会是 `null`: ```dart @@ -1922,10 +1926,17 @@ If someone tries to create a `Scrollbar` without specifying the `child` argument, then the analyzer reports an issue. +当你创建一个不带 `child` 参数的 `Scrollbar` 时, +分析器就会报告这里出了问题。 + {{site.alert.note}} + A parameter marked as `required` can still be nullable: + 一个标记了 `required` 的参数 + 仍然是可空的类型: + ```dart const Scrollbar({super.key, required [!Widget?!] child}); diff --git a/src/null-safety/migration-guide.md b/src/null-safety/migration-guide.md index 01be573b8..de040f40e 100644 --- a/src/null-safety/migration-guide.md +++ b/src/null-safety/migration-guide.md @@ -234,7 +234,8 @@ or give it a [default value][]. 你的代码里大部分需要更改的代码,都是可以轻易推导的。 例如,如果一个变量可以为空,[它的类型需要 `?` 后缀][nullable type]。 -一个不可以为空的命名参数,需要使用 [`required` 标记][required]。 +一个不可以为空的命名参数,需要使用 [`required` 标记][required], +或者给定其一个 [默认值][default value]。 You have two options for migrating:
Commits