diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 98b2f12aa..e0edebc0f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -38,10 +38,10 @@ jobs: experimental: false continue-on-error: ${{ matrix.experimental }} steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 with: submodules: recursive - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - name: Fetch Dart packages @@ -57,10 +57,10 @@ jobs: name: Check if code excerpts are up to date runs-on: ubuntu-latest steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 with: submodules: recursive - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: stable - name: Fetch Dart packages @@ -72,10 +72,10 @@ jobs: name: Build site and check links runs-on: ubuntu-latest steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 with: submodules: recursive - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: stable - name: Fetch Dart packages @@ -101,10 +101,10 @@ jobs: name: Check if text can be replaced with site variables runs-on: ubuntu-latest steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 with: submodules: recursive - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: stable - name: Fetch Dart packages @@ -116,10 +116,10 @@ jobs: name: Validate Firebase configuration runs-on: ubuntu-latest steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 with: submodules: recursive - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: stable - name: Fetch Dart packages @@ -141,10 +141,10 @@ jobs: FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }} FIREBASE_PROJECT: default steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 with: submodules: recursive - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: stable - name: Fetch Dart packages diff --git a/.github/workflows/compile_archive_js.yml b/.github/workflows/compile_archive_js.yml index 676c012c8..ce79d45a9 100644 --- a/.github/workflows/compile_archive_js.yml +++ b/.github/workflows/compile_archive_js.yml @@ -16,11 +16,11 @@ jobs: github.repository == 'cfug/dart.cn' }} runs-on: ubuntu-latest steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 with: submodules: recursive token: ${{ secrets.CFUG_DEV_TOKEN }} - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 - name: Build Dart archives downloading JS run: > bash tool/get-dart/archive/compile.sh diff --git a/eleventy.config.js b/eleventy.config.js index 9c848ee92..feb6c9378 100644 --- a/eleventy.config.js +++ b/eleventy.config.js @@ -127,7 +127,7 @@ export default function (eleventyConfig) { // Save in `_site/assets/img` and update links to there. eleventyConfig.addPlugin(eleventyImageTransformPlugin, { extensions: 'html', - formats: ['avif', 'webp', 'png', 'svg'], + formats: ['webp', 'png', 'svg'], svgShortCircuit: true, widths: ['auto'], defaultAttributes: { @@ -136,6 +136,9 @@ export default function (eleventyConfig) { }, urlPath: '/assets/img/', outputDir: '_site/assets/img/', + sharpOptions: { + animated: true, + }, }); } else { // To be more consistent with the production build, @@ -151,6 +154,9 @@ export default function (eleventyConfig) { }, urlPath: '/assets/img/', outputDir: '_site/assets/img/', + sharpOptions: { + animated: true, + }, }); } diff --git a/examples/language/lib/class_modifiers/ex1/b.dart b/examples/language/lib/class_modifiers/ex1/b.dart index 65aa079a7..9460230f0 100644 --- a/examples/language/lib/class_modifiers/ex1/b.dart +++ b/examples/language/lib/class_modifiers/ex1/b.dart @@ -9,12 +9,11 @@ Vehicle myVehicle = Vehicle(); // Can be extended. class Car extends Vehicle { int passengers = 4; - // #enddocregion abstract-usages + @override void moveForward(int meters) { // ... } - // #docregion abstract-usages } // Can be implemented. diff --git a/examples/language/lib/patterns/destructuring.dart b/examples/language/lib/patterns/destructuring.dart index b44ad4554..d291b5255 100644 --- a/examples/language/lib/patterns/destructuring.dart +++ b/examples/language/lib/patterns/destructuring.dart @@ -42,6 +42,10 @@ void main() { return ('doug', 25); } + ({String name, int age}) getData() { + return (name: 'doug', age: 25); + } + var json = {}; { @@ -57,6 +61,13 @@ void main() { var (name, age) = userInfo(json); // #enddocregion destructure-multiple-returns-2 } + + { + // #docregion destructure-multiple-returns-3 + final (:name, :age) = + getData(); // For example, return (name: 'doug', age: 25); + // #enddocregion destructure-multiple-returns-3 + } } { // #docregion destructure-class-instances diff --git a/examples/non_promotion/lib/non_promotion.dart b/examples/non_promotion/lib/non_promotion.dart index 5d5496b5a..b7979d2c9 100644 --- a/examples/non_promotion/lib/non_promotion.dart +++ b/examples/non_promotion/lib/non_promotion.dart @@ -1,6 +1,15 @@ // ignore_for_file: expected_executable, missing_statement // ignore_for_file: unused_local_variable, unused_element // ignore_for_file: prefer_function_declarations_over_variables +// ignore_for_file: prefer_if_null_operators + +// #docregion not-field, conflicting-getter +import 'dart:math'; +// #enddocregion not-field, conflicting-getter + +// #docregion mock +import 'package:mockito/mockito.dart'; +// #enddocregion mock class C1 { int? i; @@ -242,3 +251,137 @@ void miscDeclAnalyzedButNotTested() { // #enddocregion closure-write-capture } } + +// #docregion this +extension on int? { + int get valueOrZero { + final self = this; + return self == null ? 0 : self; + } +} +// #enddocregion this + +// #docregion private +class PrivateFieldExample { + final int? _val; + PrivateFieldExample(this._val); +} + +void test(PrivateFieldExample x) { + if (x._val != null) { + print(x._val + 1); + } +} +// #enddocregion private + +// #docregion final +class FinalExample { + final int? _immutablePrivateField; + FinalExample(this._immutablePrivateField); + + void f() { + if (_immutablePrivateField != null) { + int i = _immutablePrivateField; // OK + } + } +} +// #enddocregion final + +// #docregion not-field +abstract class NotFieldExample { + int? get _value => Random().nextBool() ? 123 : null; +} + +void f(NotFieldExample x) { + final value = x._value; + if (value != null) { + print(value.isEven); // OK + } +} +// #enddocregion not-field + +// #docregion external +class ExternalExample { + external final int? _externalField; + + void f() { + final i = _externalField; + if (i != null) { + print(i.isEven); // OK + } + } +} +// #enddocregion external + +// #docregion conflicting-getter +class GetterExample { + final int? _overridden; + GetterExample(this._overridden); +} + +class Override implements GetterExample { + @override + int? get _overridden => Random().nextBool() ? 1 : null; +} + +void testParity(GetterExample x) { + final i = x._overridden; + if (i != null) { + print(i.isEven); // OK + } +} +// #enddocregion conflicting-getter + +// #docregion unrelated +class UnrelatedExample { + final int? _i; + UnrelatedExample(this._i); +} + +class Unrelated { + int? get _j => Random().nextBool() ? 1 : null; +} + +void f2(UnrelatedExample x) { + if (x._i != null) { + int i = x._i; // OK + } +} +// #enddocregion unrelated + +// #docregion conflicting-field +class FieldExample { + final int? _overridden; + FieldExample(this._overridden); +} + +class Override2 implements FieldExample { + @override + int? _overridden; +} + +void f3(FieldExample x) { + final i = x._overridden; + if (i != null) { + print(i.isEven); // OK + } +} +// #enddocregion conflicting-field + +// #docregion mock +class MockingExample { + final int? _i; + MockingExample(this._i); +} + +class MockExample extends Mock implements MockingExample { + @override + late final int? _i; +} + +void f4(MockingExample x) { + if (x._i != null) { + int i = x._i; // OK + } +} +// #enddocregion mock diff --git a/examples/non_promotion/pubspec.yaml b/examples/non_promotion/pubspec.yaml index c715b2614..4a9ed42f1 100644 --- a/examples/non_promotion/pubspec.yaml +++ b/examples/non_promotion/pubspec.yaml @@ -5,5 +5,8 @@ version: 0.0.1 environment: sdk: ^3.4.0 +dependencies: + mockito: ^5.4.4 + dev_dependencies: lints: ^4.0.0 diff --git a/firebase.json b/firebase.json index b74ffe1cf..e62dcef53 100644 --- a/firebase.json +++ b/firebase.json @@ -45,7 +45,7 @@ { "source": "/articles/archive/event-loop", "destination": "https://medium.com/dartlang/dart-asynchronous-programming-isolates-and-event-loops-bffc3e296a6a", "type": 301 }, { "source": "/articles/archive/numeric-computation", "destination": "/guides/language/numbers", "type": 301 }, { "source": "/articles/archive/zones", "destination": "/libraries/async/zones", "type": 301 }, - { "source": "/articles/await-async", "destination": "/codelabs/async-await", "type": 301 }, + { "source": "/articles/await-async", "destination": "/libraries/async/async-await", "type": 301 }, { "source": "/articles/broadcast-streams", "destination": "https://medium.com/dartlang/dart-asynchronous-programming-streams-dab952023ed7", "type": 301 }, { "source": "/articles/converters-and-codecs", "destination": "/libraries/convert/converters-and-codecs", "type": 301 }, { "source": "/articles/creating-streams", "destination": "/libraries/async/creating-streams", "type": 301 }, @@ -64,7 +64,7 @@ { "source": "/articles/js-dart-interop", "destination": "/web/libraries#js-interop", "type": 301 }, { "source": "/articles/json-web-service", "destination": "/guides/json", "type": 301 }, { "source": "/articles/language", "destination": "/language", "type": 301 }, - { "source": "/articles/language/await-async", "destination": "/codelabs/async-await", "type": 301 }, + { "source": "/articles/language/await-async", "destination": "/libraries/async/async-await", "type": 301 }, { "source": "/articles/language/mixins", "destination": "/language/mixins", "type": 301 }, { "source": "/articles/language/optional-types", "destination": "/resources/faq#types", "type": 301 }, { "source": "/articles/libraries", "destination": "/libraries", "type": 301 }, @@ -84,7 +84,7 @@ { "source": "/articles/server{,/**}", "destination": "/server", "type": 301 }, { "source": "/articles/snapshots", "destination": "/tools/dart-compile", "type": 301 }, { "source": "/articles/style-guide{,/**}", "destination": "/effective-dart/style", "type": 301 }, - { "source": "/articles/using-future-based-apis{,/**}", "destination": "/codelabs/async-await", "type": 301 }, + { "source": "/articles/using-future-based-apis{,/**}", "destination": "/libraries/async/async-await", "type": 301 }, { "source": "/articles/why-dart-types", "destination": "/resources/faq#types", "type": 301 }, { "source": "/articles/zones", "destination": "/libraries/async/zones", "type": 301 }, { "source": "/assets/dart-logo-for-shares*.png", "destination": "/assets/img/logo/dart-logo-for-shares.png", "type": 301 }, @@ -96,6 +96,9 @@ { "source": "/cl", "destination": "https://dart-review.googlesource.com/q/status:open+-is:wip", "type": 301 }, { "source": "/cl/:rest*", "destination": "https://dart-review.googlesource.com/c/sdk/+/:rest*", "type": 301 }, { "source": "/cloud{,/**}", "destination": "/server/google-cloud", "type": 301 }, + { "source": "/codelabs", "destination": "/tutorials", "type": 301 }, + { "source": "/codelabs/async-await", "destination": "/libraries/async/async-await", "type": 301 }, + { "source": "/codelabs/dart-cheatsheet", "destination": "/resources/dart-cheatsheet", "type": 301 }, { "source": "/codelabs/null-safety{,/**}", "destination": "/null-safety/understanding-null-safety", "type": 301 }, { "source": "/codelabs/server{,/**}", "destination": "/tutorials/server/httpserver", "type": 301 }, { "source": "/code-of-conduct", "destination": "/community/code-of-conduct", "type": 301 }, @@ -139,7 +142,7 @@ { "source": "/docs/tutorials/cmdline", "destination": "/tutorials/server/cmdline", "type": 301 }, { "source": "/docs/tutorials/connect-dart-html", "destination": "/library/dart-html", "type": 301 }, { "source": "/docs/tutorials/fetchdata", "destination": "/tutorials/server/fetch-data", "type": 301 }, - { "source": "/docs/tutorials/futures", "destination": "/codelabs/async-await", "type": 301 }, + { "source": "/docs/tutorials/futures", "destination": "/libraries/async/async-await", "type": 301 }, { "source": "/docs/tutorials/get-started", "destination": "/tutorials/server/get-started", "type": 301 }, { "source": "/docs/tutorials/httpserver", "destination": "/tutorials/server/httpserver", "type": 301 }, { "source": "/docs/tutorials/indexeddb{,/**}", "destination": "https://api.dart.cn/stable/dart-indexed_db/dart-indexed_db-library.html", "type": 301 }, @@ -277,6 +280,9 @@ { "source": "/stable{,/**}", "destination": "https://api.dart.cn/stable", "type": 301 }, { "source": "/support/faq?(.html)", "destination": "/resources/faq", "type": 301 }, { "source": "/support{,/**}", "destination": "/community", "type": 301 }, + + { "source": "/to/main-function", "destination": "/language/functions#main", "type": 301 }, + { "source": "/tools/**/download{,.html,/**}", "destination": "/get-dart", "type": 301 }, { "source": "/tools/**/private-files?(.html)", "destination": "/guides/libraries/private-files", "type": 301 }, { "source": "/tools/analyzer", "destination": "/tools/dart-analyze", "type": 301 }, @@ -317,7 +323,7 @@ { "source": "/tutorials/dart-vm", "destination": "/tutorials/server", "type": 301 }, { "source": "/tutorials/dart-vm/:page*", "destination": "/tutorials/server/:page*", "type": 301 }, { "source": "/tutorials/language", "destination": "/language", "type": 301 }, - { "source": "/tutorials/language/futures", "destination": "/codelabs/async-await", "type": 301 }, + { "source": "/tutorials/language/futures", "destination": "/libraries/async/async-await", "type": 301 }, { "source": "/tutorials/language/streams", "destination": "/libraries/async/using-streams", "type": 301 }, { "source": "/tutorials/libraries", "destination": "/libraries", "type": 301 }, { "source": "/tutorials/libraries/shared-pkgs", "destination": "/guides/packages", "type": 301 }, diff --git a/package.json b/package.json index 681d57e60..146fee9f4 100644 --- a/package.json +++ b/package.json @@ -22,9 +22,9 @@ "bootstrap-scss": "^4.6.2" }, "devDependencies": { - "@11ty/eleventy": "3.0.0-alpha.10", + "@11ty/eleventy": "3.0.0-alpha.14", "@11ty/eleventy-img": "5.0.0-beta.4", - "firebase-tools": "^13.10.2", + "firebase-tools": "^13.12.0", "hast-util-from-html": "^2.0.1", "hast-util-select": "^6.0.2", "hast-util-to-text": "^4.0.2", @@ -36,7 +36,7 @@ "markdown-it-container": "^4.0.0", "markdown-it-deflist": "^3.0.0", "markdown-it-table": "^4.1.1", - "sass": "^1.77.4", - "shiki": "^1.6.1" + "sass": "^1.77.6", + "shiki": "^1.10.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b9d88a615..99e6fa698 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,14 +13,14 @@ importers: version: 4.6.2 devDependencies: '@11ty/eleventy': - specifier: 3.0.0-alpha.10 - version: 3.0.0-alpha.10 + specifier: 3.0.0-alpha.14 + version: 3.0.0-alpha.14 '@11ty/eleventy-img': specifier: 5.0.0-beta.4 version: 5.0.0-beta.4(encoding@0.1.13) firebase-tools: - specifier: ^13.10.2 - version: 13.10.2(encoding@0.1.13) + specifier: ^13.12.0 + version: 13.12.0(encoding@0.1.13) hast-util-from-html: specifier: ^2.0.1 version: 2.0.1 @@ -55,11 +55,11 @@ importers: specifier: ^4.1.1 version: 4.1.1 sass: - specifier: ^1.77.4 - version: 1.77.4 + specifier: ^1.77.6 + version: 1.77.6 shiki: - specifier: ^1.6.1 - version: 1.6.1 + specifier: ^1.10.0 + version: 1.10.0 packages: @@ -69,8 +69,8 @@ packages: '@11ty/dependency-tree@3.0.0': resolution: {integrity: sha512-+M+/KdAptDTK4USkI124CKoScvt2y0v1EoLBjS2rUi9zydjWgEC7+EJJ7Eu1DXuObe0JmY09LORjdBGKNPxgtg==} - '@11ty/eleventy-dev-server@2.0.0': - resolution: {integrity: sha512-hqxQV92Bos0uyZa3P+BAX0nQqjQQMi4vCSxcQHNYEB/jjGV6CnurLBSn63U1VoixGAL4SpHm9OdTa2oVOTUx6Q==} + '@11ty/eleventy-dev-server@2.0.1': + resolution: {integrity: sha512-G92KbOx5vg2G3mlQQ1B0+L+Ni7pcn1yeMgQdnT8b2G20ZnbGNtuGYEPehbQV4Xqr2iAtoBfbihNskbLDoVtNOg==} engines: {node: '>=18'} hasBin: true @@ -90,8 +90,12 @@ packages: resolution: {integrity: sha512-Zy2leMK1DQR6Q6ZPSagv7QpJaAz9uVbb+RmVetYFp3foMeQtOSZx7w2u5daRFmP+PeNq9vO9H4xtBToYFWZwHA==} engines: {node: '>=12'} - '@11ty/eleventy@3.0.0-alpha.10': - resolution: {integrity: sha512-lnymV2KjhxPNs+e4otrjwr/kh7AEE/yTAwgVRtpdo8BA+zSDHaw+aeq/2L+h2nhQ9Z1a4ExIjQqk7K51E40tlA==} + '@11ty/eleventy-utils@1.0.3': + resolution: {integrity: sha512-nULO91om7vQw4Y/UBjM8i7nJ1xl+/nyK4rImZ41lFxiY2d+XUz7ChAj1CDYFjrLZeu0utAYJTZ45LlcHTkUG4g==} + engines: {node: '>=12'} + + '@11ty/eleventy@3.0.0-alpha.14': + resolution: {integrity: sha512-SQGvi/0cSrgyjhTocO8nGpivQbZBXnFlVLp1M3H8xcdvpXYgCVHiEYvrY79TnDd9Nxvj5QtsQuCiselJb3X16g==} engines: {node: '>=18'} hasBin: true @@ -375,8 +379,8 @@ packages: '@protobufjs/utf8@1.1.0': resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} - '@shikijs/core@1.6.1': - resolution: {integrity: sha512-CqYyepN4SnBopaoXYwng4NO8riB5ask/LTCkhOFq+GNGtr2X+aKeD767eYdqYukeixEUvv4bXdyTYVaogj7KBw==} + '@shikijs/core@1.10.0': + resolution: {integrity: sha512-BZcr6FCmPfP6TXaekvujZcnkFmJHZ/Yglu97r/9VjzVndQA56/F4WjUKtJRQUnK59Wi7p/UTAOekMfCJv7jnYg==} '@sindresorhus/slugify@2.2.1': resolution: {integrity: sha512-MkngSCRZ8JdSOCHRaYd+D01XhvU3Hjy6MGl06zhOk614hp9EOAp5gIkBeQg7wtmxpitU6eAL4kdiRMcJa2dlrw==} @@ -513,17 +517,13 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} - archiver-utils@2.1.0: - resolution: {integrity: sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==} - engines: {node: '>= 6'} - - archiver-utils@3.0.4: - resolution: {integrity: sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==} - engines: {node: '>= 10'} + archiver-utils@5.0.2: + resolution: {integrity: sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==} + engines: {node: '>= 14'} - archiver@5.3.2: - resolution: {integrity: sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==} - engines: {node: '>= 10'} + archiver@7.0.1: + resolution: {integrity: sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==} + engines: {node: '>= 14'} argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -587,9 +587,15 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + b4a@1.6.6: + resolution: {integrity: sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==} + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + bare-events@2.4.2: + resolution: {integrity: sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==} + base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -651,8 +657,9 @@ packages: resolution: {integrity: sha512-uA9fOtlTRC0iqKfzff1W34DXUA3GyVqbUaeo3Rw3d4gd1eavKVCETXrn3NzO74W+UVkG3UHu8WxUi+XvKI/huA==} engines: {node: '>= 10.16.0'} - buffer-crc32@0.2.13: - resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + buffer-crc32@1.0.0: + resolution: {integrity: sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==} + engines: {node: '>=8.0.0'} buffer-equal-constant-time@1.0.1: resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} @@ -663,6 +670,9 @@ packages: buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + bytes@3.0.0: resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==} engines: {node: '>= 0.8'} @@ -704,6 +714,9 @@ packages: chardet@0.7.0: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + chardet@2.0.0: + resolution: {integrity: sha512-xVgPpulCooDjY6zH4m9YW3jbkaBe3FKIAvF5sj5t7aBNsVl2ljIE+xwJ4iNgiDZHFQvNIpjdKdVOQvvk5ZfxbQ==} + chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} @@ -814,9 +827,9 @@ packages: resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==} engines: {node: '>= 6'} - compress-commons@4.1.2: - resolution: {integrity: sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==} - engines: {node: '>= 10'} + compress-commons@6.0.2: + resolution: {integrity: sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==} + engines: {node: '>= 14'} compressible@2.0.18: resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} @@ -867,9 +880,9 @@ packages: engines: {node: '>=0.8'} hasBin: true - crc32-stream@4.0.3: - resolution: {integrity: sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==} - engines: {node: '>= 10'} + crc32-stream@6.0.0: + resolution: {integrity: sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==} + engines: {node: '>= 14'} cross-env@5.2.1: resolution: {integrity: sha512-1yHhtcfAd1r4nwQgknowuUNfIT9E8dOMMspC36g45dN+iD1blloi7xp8X/xAIDnjHWyt1uQ8PHk2fkNaym7soQ==} @@ -932,6 +945,15 @@ packages: supports-color: optional: true + debug@4.3.5: + resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + deep-equal-in-any-order@2.0.6: resolution: {integrity: sha512-RfnWHQzph10YrUjvWwhd15Dne8ciSJcZ3U6OD7owPwiVwsdE5IFSoZGg8rlwJD11ES+9H5y8j3fCofviRHOqLQ==} @@ -1149,6 +1171,10 @@ packages: events-listener@1.1.0: resolution: {integrity: sha512-Kd3EgYfODHueq6GzVfs/VUolh2EgJsS8hkO3KpnDrxVjU3eq63eXM2ujXkhPP+OkeUOhL8CxdfZbQXzryb5C4g==} + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + exegesis-express@4.0.0: resolution: {integrity: sha512-V2hqwTtYRj0bj43K4MCtm0caD97YWkqOUHFMRCBW5L1x9IjyqOEc7Xa4oQjjiFbeFOSQzzwPV+BzXsQjSz08fw==} engines: {node: '>=6.0.0', npm: '>5.0.0'} @@ -1178,6 +1204,9 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + fast-fifo@1.3.2: + resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + fast-glob@3.3.2: resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} engines: {node: '>=8.6.0'} @@ -1214,8 +1243,8 @@ packages: resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} engines: {node: '>= 0.8'} - firebase-tools@13.10.2: - resolution: {integrity: sha512-vdD2//pncVg0jf2Wxo4jNJVxOiS4yJE7lx60H0xONkVW4P+hg4xe7y0O+RxOzajw4hbrUq4geyRZDQK1VlIKuw==} + firebase-tools@13.12.0: + resolution: {integrity: sha512-hr3rqrWeeiNshVzmVSeQkCOSGUSKMxZs+ztairg4r6wteGUOVz56DrYsDMTUxjqH5zPxz5pxK9cvJi4M4ER13g==} engines: {node: '>=18.0.0 || >=20.0.0'} hasBin: true @@ -1249,9 +1278,6 @@ packages: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} - fs-constants@1.0.0: - resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} - fs-extra@10.1.0: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} @@ -1729,8 +1755,8 @@ packages: linkify-it@5.0.0: resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} - liquidjs@10.13.1: - resolution: {integrity: sha512-QCQ69sbyMdA1970NEsG7KdQoKi6N+lGg55izisvKvrrRO1nrpS/YBAnzDndR13exYB4xE9A87qdOMuaXPn9v9A==} + liquidjs@10.14.0: + resolution: {integrity: sha512-Zjg35Yo3L/2aNy7QkICha/ulbXRtZS7oRenWyDDfw+J34Xy3fOKWWHxASC9r0gbxN661nrwmG/kOIKHfYcVk4Q==} engines: {node: '>=14'} hasBin: true @@ -1743,15 +1769,6 @@ packages: lodash.camelcase@4.3.0: resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} - lodash.defaults@4.2.0: - resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} - - lodash.difference@4.5.0: - resolution: {integrity: sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==} - - lodash.flatten@4.4.0: - resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} - lodash.includes@4.3.0: resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} @@ -1782,9 +1799,6 @@ packages: lodash.snakecase@4.1.1: resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} - lodash.union@4.6.0: - resolution: {integrity: sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==} - lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} @@ -2288,6 +2302,10 @@ packages: process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + progress@2.0.3: resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} engines: {node: '>=0.4.0'} @@ -2359,6 +2377,9 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + queue-tick@1.0.1: + resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==} + queue@6.0.2: resolution: {integrity: sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==} @@ -2391,6 +2412,10 @@ packages: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} + readable-stream@4.5.2: + resolution: {integrity: sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + readdir-glob@1.1.3: resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==} @@ -2458,6 +2483,11 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true + rimraf@5.0.7: + resolution: {integrity: sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==} + engines: {node: '>=14.18'} + hasBin: true + router@1.3.8: resolution: {integrity: sha512-461UFH44NtSfIlS83PUg2N7OZo86BC/kB3dY77gJdsODsBhhw7+2uE0tzTINxrY9CahCUVk1VhpWCA5i1yoIEg==} engines: {node: '>= 0.8'} @@ -2485,8 +2515,8 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - sass@1.77.4: - resolution: {integrity: sha512-vcF3Ckow6g939GMA4PeU7b2K/9FALXk2KF9J87txdHzXbUF9XRQRwSxcAs/fGaTnJeBFd7UoV22j3lzMLdM0Pw==} + sass@1.77.6: + resolution: {integrity: sha512-ByXE1oLD79GVq9Ht1PeHWCPMPB8XHpBuz1r85oByKHjZY6qV6rWnQovQzXJXuQ/XyE1Oj3iPk3lo28uzaRA2/Q==} engines: {node: '>=14.0.0'} hasBin: true @@ -2549,8 +2579,8 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - shiki@1.6.1: - resolution: {integrity: sha512-1Pu/A1rtsG6HZvQm4W0NExQ45e02og+rPog7PDaFDiMumZgOYnZIu4JtGQeAIfMwdbKSjJQoCUr79vDLKUUxWA==} + shiki@1.10.0: + resolution: {integrity: sha512-YD2sXQ+TMD/F9BimV9Jn0wj35pqOvywvOG/3PB6hGHyGKlM7TJ9tyJ02jOb2kF8F0HfJwKNYrh3sW7jEcuRlXA==} side-channel@1.0.6: resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} @@ -2644,6 +2674,9 @@ packages: stream-shift@1.0.3: resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==} + streamx@2.18.0: + resolution: {integrity: sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ==} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -2690,9 +2723,8 @@ packages: resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==} engines: {node: '>=8'} - tar-stream@2.2.0: - resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} - engines: {node: '>=6'} + tar-stream@3.1.7: + resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} tar@6.2.1: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} @@ -2710,6 +2742,9 @@ packages: engines: {node: '>=10'} hasBin: true + text-decoder@1.1.0: + resolution: {integrity: sha512-TmLJNj6UgX8xcUZo4UDStGQtDiTzF7BzWlzn9g7UWrjkpHr5uJTK1ld16wZ3LXb2vb6jH8qU89dW5whuMdXYdw==} + text-hex@1.0.0: resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} @@ -2967,9 +3002,9 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - zip-stream@4.1.1: - resolution: {integrity: sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==} - engines: {node: '>= 10'} + zip-stream@6.0.1: + resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==} + engines: {node: '>= 14'} zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -2978,20 +3013,20 @@ snapshots: '@11ty/dependency-tree-esm@1.0.0': dependencies: - '@11ty/eleventy-utils': 1.0.2 + '@11ty/eleventy-utils': 1.0.3 acorn: 8.11.3 dependency-graph: 0.11.0 normalize-path: 3.0.0 '@11ty/dependency-tree@3.0.0': dependencies: - '@11ty/eleventy-utils': 1.0.2 + '@11ty/eleventy-utils': 1.0.3 - '@11ty/eleventy-dev-server@2.0.0': + '@11ty/eleventy-dev-server@2.0.1': dependencies: - '@11ty/eleventy-utils': 1.0.2 + '@11ty/eleventy-utils': 1.0.3 chokidar: 3.6.0 - debug: 4.3.4 + debug: 4.3.5 dev-ip: 1.0.1 finalhandler: 1.2.0 mime: 3.0.0 @@ -3033,7 +3068,7 @@ snapshots: '@11ty/eleventy-plugin-bundle@2.0.2': dependencies: - debug: 4.3.4 + debug: 4.3.5 transitivePeerDependencies: - supports-color @@ -3041,20 +3076,25 @@ snapshots: dependencies: normalize-path: 3.0.0 - '@11ty/eleventy@3.0.0-alpha.10': + '@11ty/eleventy-utils@1.0.3': + dependencies: + normalize-path: 3.0.0 + + '@11ty/eleventy@3.0.0-alpha.14': dependencies: '@11ty/dependency-tree': 3.0.0 '@11ty/dependency-tree-esm': 1.0.0 - '@11ty/eleventy-dev-server': 2.0.0 + '@11ty/eleventy-dev-server': 2.0.1 '@11ty/eleventy-plugin-bundle': 2.0.2 - '@11ty/eleventy-utils': 1.0.2 + '@11ty/eleventy-utils': 1.0.3 '@11ty/lodash-custom': 4.17.21 '@11ty/posthtml-urls': 1.0.0 '@sindresorhus/slugify': 2.2.1 bcp-47-normalize: 2.3.0 + chardet: 2.0.0 chokidar: 3.6.0 cross-spawn: 7.0.3 - debug: 4.3.4 + debug: 4.3.5 dependency-graph: 1.0.0 fast-glob: 3.3.2 graceful-fs: 4.2.11 @@ -3062,7 +3102,7 @@ snapshots: is-glob: 4.0.3 iso-639-1: 3.1.2 kleur: 4.1.5 - liquidjs: 10.13.1 + liquidjs: 10.14.0 luxon: 3.4.4 markdown-it: 14.1.0 micromatch: 4.0.7 @@ -3355,7 +3395,7 @@ snapshots: '@protobufjs/utf8@1.1.0': {} - '@shikijs/core@1.6.1': {} + '@shikijs/core@1.10.0': {} '@sindresorhus/slugify@2.2.1': dependencies: @@ -3426,13 +3466,13 @@ snapshots: agent-base@6.0.2: dependencies: - debug: 4.3.4 + debug: 4.3.5 transitivePeerDependencies: - supports-color agent-base@7.1.1: dependencies: - debug: 4.3.4 + debug: 4.3.5 transitivePeerDependencies: - supports-color @@ -3487,41 +3527,25 @@ snapshots: normalize-path: 3.0.0 picomatch: 2.3.1 - archiver-utils@2.1.0: - dependencies: - glob: 7.2.3 - graceful-fs: 4.2.11 - lazystream: 1.0.1 - lodash.defaults: 4.2.0 - lodash.difference: 4.5.0 - lodash.flatten: 4.4.0 - lodash.isplainobject: 4.0.6 - lodash.union: 4.6.0 - normalize-path: 3.0.0 - readable-stream: 2.3.8 - - archiver-utils@3.0.4: + archiver-utils@5.0.2: dependencies: - glob: 7.2.3 + glob: 10.4.1 graceful-fs: 4.2.11 + is-stream: 2.0.1 lazystream: 1.0.1 - lodash.defaults: 4.2.0 - lodash.difference: 4.5.0 - lodash.flatten: 4.4.0 - lodash.isplainobject: 4.0.6 - lodash.union: 4.6.0 + lodash: 4.17.21 normalize-path: 3.0.0 - readable-stream: 3.6.2 + readable-stream: 4.5.2 - archiver@5.3.2: + archiver@7.0.1: dependencies: - archiver-utils: 2.1.0 + archiver-utils: 5.0.2 async: 3.2.5 - buffer-crc32: 0.2.13 - readable-stream: 3.6.2 + buffer-crc32: 1.0.0 + readable-stream: 4.5.2 readdir-glob: 1.1.3 - tar-stream: 2.2.0 - zip-stream: 4.1.1 + tar-stream: 3.1.7 + zip-stream: 6.0.1 argparse@1.0.10: dependencies: @@ -3567,8 +3591,13 @@ snapshots: asynckit@0.4.0: {} + b4a@1.6.6: {} + balanced-match@1.0.2: {} + bare-events@2.4.2: + optional: true + base64-js@1.5.1: {} basic-auth-connect@1.0.0: {} @@ -3651,7 +3680,7 @@ snapshots: dependencies: duplexer: 0.1.1 - buffer-crc32@0.2.13: {} + buffer-crc32@1.0.0: {} buffer-equal-constant-time@1.0.1: {} @@ -3662,6 +3691,11 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + bytes@3.0.0: {} bytes@3.1.2: {} @@ -3713,6 +3747,8 @@ snapshots: chardet@0.7.0: {} + chardet@2.0.0: {} + chokidar@3.6.0: dependencies: anymatch: 3.1.3 @@ -3818,12 +3854,13 @@ snapshots: commander@5.1.0: {} - compress-commons@4.1.2: + compress-commons@6.0.2: dependencies: - buffer-crc32: 0.2.13 - crc32-stream: 4.0.3 + crc-32: 1.2.2 + crc32-stream: 6.0.0 + is-stream: 2.0.1 normalize-path: 3.0.0 - readable-stream: 3.6.2 + readable-stream: 4.5.2 compressible@2.0.18: dependencies: @@ -3885,10 +3922,10 @@ snapshots: crc-32@1.2.2: {} - crc32-stream@4.0.3: + crc32-stream@6.0.0: dependencies: crc-32: 1.2.2 - readable-stream: 3.6.2 + readable-stream: 4.5.2 cross-env@5.2.1: dependencies: @@ -3932,6 +3969,10 @@ snapshots: dependencies: ms: 2.1.2 + debug@4.3.5: + dependencies: + ms: 2.1.2 + deep-equal-in-any-order@2.0.6: dependencies: lodash.mapvalues: 4.6.0 @@ -4114,6 +4155,8 @@ snapshots: events-listener@1.1.0: {} + events@3.3.0: {} + exegesis-express@4.0.0: dependencies: exegesis: 4.1.2 @@ -4195,6 +4238,8 @@ snapshots: fast-deep-equal@3.1.3: {} + fast-fifo@1.3.2: {} + fast-glob@3.3.2: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -4249,13 +4294,13 @@ snapshots: transitivePeerDependencies: - supports-color - firebase-tools@13.10.2(encoding@0.1.13): + firebase-tools@13.12.0(encoding@0.1.13): dependencies: '@google-cloud/cloud-sql-connector': 1.3.0(encoding@0.1.13) '@google-cloud/pubsub': 4.4.0(encoding@0.1.13) abort-controller: 3.0.0 ajv: 6.12.6 - archiver: 5.3.2 + archiver: 7.0.1 async-lock: 1.3.2 body-parser: 1.20.2 chokidar: 3.6.0 @@ -4277,7 +4322,7 @@ snapshots: fs-extra: 10.1.0 fuzzy: 0.1.3 gaxios: 6.6.0(encoding@0.1.13) - glob: 7.2.3 + glob: 10.4.1 google-auth-library: 9.10.0(encoding@0.1.13) inquirer: 8.2.6 inquirer-autocomplete-prompt: 2.0.1(inquirer@8.2.6) @@ -4299,7 +4344,7 @@ snapshots: progress: 2.0.3 proxy-agent: 6.4.0 retry: 0.13.1 - rimraf: 3.0.2 + rimraf: 5.0.7 semver: 7.6.2 sql-formatter: 15.3.1 stream-chain: 2.2.5 @@ -4355,8 +4400,6 @@ snapshots: fresh@0.5.2: {} - fs-constants@1.0.0: {} - fs-extra@10.1.0: dependencies: graceful-fs: 4.2.11 @@ -4422,7 +4465,7 @@ snapshots: dependencies: basic-ftp: 5.0.5 data-uri-to-buffer: 6.0.2 - debug: 4.3.4 + debug: 4.3.5 fs-extra: 11.2.0 transitivePeerDependencies: - supports-color @@ -4651,28 +4694,28 @@ snapshots: dependencies: '@tootallnate/once': 2.0.0 agent-base: 6.0.2 - debug: 4.3.4 + debug: 4.3.5 transitivePeerDependencies: - supports-color http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.1 - debug: 4.3.4 + debug: 4.3.5 transitivePeerDependencies: - supports-color https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.3.4 + debug: 4.3.5 transitivePeerDependencies: - supports-color https-proxy-agent@7.0.4: dependencies: agent-base: 7.1.1 - debug: 4.3.4 + debug: 4.3.5 transitivePeerDependencies: - supports-color @@ -4947,7 +4990,7 @@ snapshots: dependencies: uc.micro: 2.1.0 - liquidjs@10.13.1: + liquidjs@10.14.0: dependencies: commander: 10.0.1 @@ -4957,12 +5000,6 @@ snapshots: lodash.camelcase@4.3.0: {} - lodash.defaults@4.2.0: {} - - lodash.difference@4.5.0: {} - - lodash.flatten@4.4.0: {} - lodash.includes@4.3.0: {} lodash.isboolean@3.0.3: {} @@ -4985,8 +5022,6 @@ snapshots: lodash.snakecase@4.1.1: {} - lodash.union@4.6.0: {} - lodash@4.17.21: {} log-symbols@4.1.0: @@ -5363,7 +5398,7 @@ snapshots: dependencies: '@tootallnate/quickjs-emscripten': 0.23.0 agent-base: 7.1.1 - debug: 4.3.4 + debug: 4.3.5 get-uri: 6.0.3 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.4 @@ -5496,6 +5531,8 @@ snapshots: process-nextick-args@2.0.1: {} + process@0.11.10: {} + progress@2.0.3: {} promise-breaker@6.0.0: {} @@ -5541,7 +5578,7 @@ snapshots: proxy-agent@6.4.0: dependencies: agent-base: 7.1.1 - debug: 4.3.4 + debug: 4.3.5 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.4 lru-cache: 7.18.3 @@ -5580,6 +5617,8 @@ snapshots: queue-microtask@1.2.3: {} + queue-tick@1.0.1: {} + queue@6.0.2: dependencies: inherits: 2.0.4 @@ -5632,6 +5671,14 @@ snapshots: string_decoder: 1.3.0 util-deprecate: 1.0.2 + readable-stream@4.5.2: + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + readdir-glob@1.1.3: dependencies: minimatch: 5.1.6 @@ -5701,6 +5748,10 @@ snapshots: dependencies: glob: 7.2.3 + rimraf@5.0.7: + dependencies: + glob: 10.4.1 + router@1.3.8: dependencies: array-flatten: 3.0.0 @@ -5731,7 +5782,7 @@ snapshots: safer-buffer@2.1.2: {} - sass@1.77.4: + sass@1.77.6: dependencies: chokidar: 3.6.0 immutable: 4.3.6 @@ -5830,9 +5881,9 @@ snapshots: shebang-regex@3.0.0: {} - shiki@1.6.1: + shiki@1.10.0: dependencies: - '@shikijs/core': 1.6.1 + '@shikijs/core': 1.10.0 side-channel@1.0.6: dependencies: @@ -5858,7 +5909,7 @@ snapshots: socks-proxy-agent@8.0.3: dependencies: agent-base: 7.1.1 - debug: 4.3.4 + debug: 4.3.5 socks: 2.8.3 transitivePeerDependencies: - supports-color @@ -5917,6 +5968,14 @@ snapshots: stream-shift@1.0.3: {} + streamx@2.18.0: + dependencies: + fast-fifo: 1.3.2 + queue-tick: 1.0.1 + text-decoder: 1.1.0 + optionalDependencies: + bare-events: 2.4.2 + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -5986,13 +6045,11 @@ snapshots: has-flag: 4.0.0 supports-color: 7.2.0 - tar-stream@2.2.0: + tar-stream@3.1.7: dependencies: - bl: 4.1.0 - end-of-stream: 1.4.4 - fs-constants: 1.0.0 - inherits: 2.0.4 - readable-stream: 3.6.2 + b4a: 1.6.6 + fast-fifo: 1.3.2 + streamx: 2.18.0 tar@6.2.1: dependencies: @@ -6028,6 +6085,10 @@ snapshots: commander: 2.20.3 source-map-support: 0.5.21 + text-decoder@1.1.0: + dependencies: + b4a: 1.6.6 + text-hex@1.0.0: {} through@2.3.8: {} @@ -6111,7 +6172,7 @@ snapshots: universal-analytics@0.5.3: dependencies: - debug: 4.3.4 + debug: 4.3.5 uuid: 8.3.2 transitivePeerDependencies: - supports-color @@ -6286,10 +6347,10 @@ snapshots: yocto-queue@0.1.0: {} - zip-stream@4.1.1: + zip-stream@6.0.1: dependencies: - archiver-utils: 3.0.4 - compress-commons: 4.1.2 - readable-stream: 3.6.2 + archiver-utils: 5.0.2 + compress-commons: 6.0.2 + readable-stream: 4.5.2 zwitch@2.0.4: {} diff --git a/site-shared b/site-shared index e466136cd..d50b05880 160000 --- a/site-shared +++ b/site-shared @@ -1 +1 @@ -Subproject commit e466136cd77d715352a7f86a7abf563a1cfce735 +Subproject commit d50b05880ad6405518e3a08255bcda5fa72bbf2a diff --git a/src/_data/books-dart.yml b/src/_data/books-dart.yml index aec63bf57..09feb6eef 100644 --- a/src/_data/books-dart.yml +++ b/src/_data/books-dart.yml @@ -35,3 +35,10 @@ cover: o-guia-de-dart.webp link: "https://www.casadocodigo.com.br/products/livro-dart" desc: "Fundamentos, prática, conceitos avançados e tudo mais. Embarque neste livro que te guiará no aprendizado de Dart.
Fundamentals, practice, the concepts and everything. Embark on a journey of learning Dart in Portuguese." +- title: "Основы Dart" + authors: + - Stanislav Chernyshev + publisher: Издательский дом «Питер» + cover: basics-dart.webp + link: "https://www.piter.com/collection/biblioteka-programmista/product/osnovy-dart" + desc: "Книга «Основы Dart» адресована тем, кто интересуется этим удивительным языком программирования. Вы узнаете об истории создания, синтаксисе и особенностях языка, таких как встроенные типы данных, и многом другом. В главе 2 вас ждет проект, который будет изменяться и расти вместе с вашими знаниями и навыками, а к главе 6 преобразится в полноценное клиент-серверное приложение. После каждой новой итерации проекта, вас будут ждать предложения по внесению изменений в его кодовую базу, что позволит прокачать свои hard-скиллы. Исходный код рассматриваемых в книге примеров можно найти в GitHub-репозитории автора (весь код в книге соответствует Dart 3.4)." diff --git a/src/_data/docs_cards.yml b/src/_data/docs_cards.yml index db15813d3..6aff5d233 100644 --- a/src/_data/docs_cards.yml +++ b/src/_data/docs_cards.yml @@ -12,4 +12,4 @@ url: /tools/sdk - name: Futures, async, await description: How to write asynchronous Dart code that uses futures and the async and await keywords. - url: /codelabs/async-await + url: /libraries/async/async-await diff --git a/src/_data/side-nav.yml b/src/_data/side-nav.yml index 08017af49..27d1a28e8 100644 --- a/src/_data/side-nav.yml +++ b/src/_data/side-nav.yml @@ -1,22 +1,3 @@ -- title: 样例和教程 - expanded: false - children: - - title: 语言概览 - match-page-url-exactly: true - permalink: /tutorials - - title: Codelabs - expanded: true - children: - - title: Codelabs 列表 - match-page-url-exactly: true - permalink: /codelabs - - title: Dart 速查表 - permalink: /codelabs/dart-cheatsheet - - title: 可迭代集合 - permalink: /codelabs/iterables - - title: Dart 异步编程 - permalink: /codelabs/async-await - - title: Dart 开发语言 expanded: false children: @@ -57,6 +38,8 @@ permalink: /language/patterns - title: 模式匹配类型 permalink: /language/pattern-types + - title: 实用教程 + permalink: https://codelabs.developers.google.cn/codelabs/dart-patterns-records?hl=zh-cn#0 - title: 函数方法 permalink: /language/functions - title: 控制流 @@ -138,12 +121,18 @@ - title: dart:html permalink: /libraries/dart-html - divider - - title: 使用 stream - permalink: /libraries/async/using-streams - - title: 创建 stream - permalink: /libraries/async/creating-streams - - title: Future 和错误处理 - permalink: /libraries/async/futures-error-handling + - title: 可迭代集合 + permalink: /libraries/collections/iterables + - title: 异步编程 + children: + - title: 教程 + permalink: /libraries/async/async-await + - title: Future 和错误处理 + permalink: /libraries/async/futures-error-handling + - title: 使用 stream + permalink: /libraries/async/using-streams + - title: 创建 stream + permalink: /libraries/async/creating-streams - title: 高效指南 (Effective Dart) expanded: false @@ -199,8 +188,6 @@ - title: 开发文档 expanded: false children: - - title: Futures、async 和 await - permalink: /codelabs/async-await - title: JSON permalink: /guides/json - title: Dart 中的数字 @@ -355,6 +342,8 @@ - title: 资源 expanded: false children: + - title: 语言速查表 + permalink: /resources/dart-cheatsheet - title: 破坏性改动 permalink: /resources/breaking-changes - title: 版本演变 @@ -379,6 +368,9 @@ permalink: /resources/books - title: 视频资源 permalink: /resources/videos + - title: 教程 + match-page-url-exactly: true + permalink: /tutorials - title: 相关站点 expanded: true @@ -398,6 +390,6 @@ expanded: false children: - title: 关于本站 - permalink: https://flutter.cn/about/docs-cn + permalink: https://docs.flutter.cn/about - title: 免责条款 (Disclaimer) - permalink: https://flutter.cn/disclaimer + permalink: https://docs.flutter.cn/disclaimer diff --git a/src/_includes/cookie-notice.html b/src/_includes/cookie-notice.html index 2570d9073..edbb6b27e 100644 --- a/src/_includes/cookie-notice.html +++ b/src/_includes/cookie-notice.html @@ -1,10 +1,9 @@ diff --git a/src/_layouts/default.html b/src/_layouts/default.html index 6bab9b81b..da827739d 100644 --- a/src/_layouts/default.html +++ b/src/_layouts/default.html @@ -8,6 +8,7 @@ {% endif -%} {% endif -%} + {% render 'gtags.html' %} {% include 'page-header.html', obsolete:obsolete %} diff --git a/src/_sass/_site.scss b/src/_sass/_site.scss index 37ab8050b..76d6487a7 100644 --- a/src/_sass/_site.scss +++ b/src/_sass/_site.scss @@ -12,6 +12,7 @@ @use 'components/header'; @use 'components/search'; @use 'components/sidebar'; +@use 'components/tags'; @use 'components/toc'; @use 'dartvm'; @@ -874,3 +875,21 @@ div.tabs__content h1, h2, h3, h4, h5, h6 { margin-top: 0; } } + +#skip { + top: 10px; + left: 10px; + position: absolute; + z-index: $site-z-skip; + padding: 1rem; + background-color: $site-color-primary; + color: $site-color-white; + border-radius: 0.5rem; + transform: translateY(-5rem); +} + + +#skip:focus { + opacity: 1; + transform: translateY(0); +} diff --git a/src/_sass/components/_tags.scss b/src/_sass/components/_tags.scss new file mode 100644 index 000000000..c51925075 --- /dev/null +++ b/src/_sass/components/_tags.scss @@ -0,0 +1,27 @@ +@use '../core/variables' as *; + +.tag-label { + user-select: none; + display: inline-block; + padding: 0 0.25rem; + border-radius: 0.25rem; + font-size: 0.925rem; + font-family: $site-font-family-gsans; + text-wrap: nowrap; +} + +.language-versioned-tag { + background-color: #13B9FD; +} + +.deprecated-tag { + background-color: #F2AA3A; +} + +.removed-tag { + background-color: #F3655B; +} + +.experimental-tag { + background-color: #DADCE0; +} diff --git a/src/_sass/core/_variables.scss b/src/_sass/core/_variables.scss index 331defa49..13904104f 100644 --- a/src/_sass/core/_variables.scss +++ b/src/_sass/core/_variables.scss @@ -24,9 +24,10 @@ $site-color-footer: $site-color-dark-background; $site-color-primary: $flutter-color-blue-500; // Layer stack -$site-z-header: 10000; +$site-z-header: 1000; $site-z-footer: 99; $site-z-snackbar: 150; +$site-z-skip: 2000; $hero-layer-1-z: 40; $hero-layer-2-z: 41; $hero-layer-3-z: 42; diff --git a/src/content/assets/img/cover/basics-dart.webp b/src/content/assets/img/cover/basics-dart.webp new file mode 100644 index 000000000..5c2694d26 Binary files /dev/null and b/src/content/assets/img/cover/basics-dart.webp differ diff --git a/src/content/brand.md b/src/content/brand.md index cf2b210e4..d016f7275 100644 --- a/src/content/brand.md +++ b/src/content/brand.md @@ -19,8 +19,9 @@ material, as determined by Google. Use of the Dart trademarks that is not expressly permitted by these guidelines is prohibited absent written permission from Google. -The official Dart logos can be found in the [Dart and Flutter logo -assets](https://drive.google.com/corp/drive/folders/1KXNtO9My2AMpDOF9A9Y_4aj4_BcgmDDT) Drive folder. +The official Dart logos can be found in the +[Dart and Flutter logo assets](https://services.google.com/fh/files/misc/dart_brand_guidelines_assets.zip) +archive. ## General rules that govern the use of the Dart trademarks diff --git a/src/content/codelabs/index.md b/src/content/codelabs/index.md deleted file mode 100644 index a79f71533..000000000 --- a/src/content/codelabs/index.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -# title: Codelabs -title: Dart codelabs 列表 -# description: Links to Dart codelabs. -description: Dart codelabs 列表。 -toc: false ---- - -The Dart codelabs provide a guided, -hands-on coding experience—no download required! - -尝试 Codelab 获取体验动手编码的指导。 - -## General - -### [Dart cheatsheet](/codelabs/dart-cheatsheet) - -Use DartPad to learn or remind yourself of -some of the most commonly used, yet unique features of the Dart language. - -使用最新实验版本的 DartPad 来测试,学习和了解 Dart 语言的语法和特性。 - -### [Iterable collections](/codelabs/iterables) - -### [可迭代集合](/codelabs/iterables) - -Use DartPad to learn or remind yourself of how to use -lists, sets, and other iterable collections in Dart, -with special attention to filtering and mapping values. - -使用 DartPad 学习并提醒自己如何使用 -Dart 中的列表,集合和其他可迭代集合, -特别注意过滤和映射值。 - -### [Asynchronous programming: futures, async, await](/codelabs/async-await) - -### [异步编程:futures, async, await](/codelabs/async-await) - -Use DartPad to learn or remind yourself of how to write -asynchronous code using futures and the `async` and `await` keywords. - -使用 DartPad 来学习使用 futures、async 和 await 来写异步代码。 - -### [Records and Patterns in Dart 3](https://codelabs.developers.google.com/codelabs/dart-patterns-records) - -### [Dart 3 中的记录类型和模式匹配](https://codelabs.developers.google.com/codelabs/dart-patterns-records) - -Discover Dart 3's new records and patterns features. -Learn how you can use them in a Flutter app to help you -write more readable and maintainable Dart code. - -探索 Dart 3 带来的记录类型和模式匹配。 -你可以学习如何在你的 Flutter 应用中使用它们, -带来更加可读且易于维护的 Dart 代码。 - -## Flutter - -To learn about Flutter, try one of the -[Flutter codelabs.]({{site.flutter-docs}}/codelabs) - -尝试在 [Flutter Codelab]({{site.flutter-docs}}/codelabs),学习和了解 Flutter。 diff --git a/src/content/effective-dart/style.md b/src/content/effective-dart/style.md index 4883576ae..e0f0d9463 100644 --- a/src/content/effective-dart/style.md +++ b/src/content/effective-dart/style.md @@ -36,23 +36,21 @@ Identifiers come in three flavors in Dart. 在 Dart 中标识符有三种类型。 -* `UpperCamelCase` names capitalize the first letter of each word, including - the first. +* `UpperCamelCase` names capitalize the first letter of each word, including + the first. - `UpperCamelCase` 每个单词的首字母都大写,包含第一个单词。 + `UpperCamelCase` 每个单词的首字母都大写,包含第一个单词。 -* `lowerCamelCase` names capitalize the first letter of each word, *except* - the first which is always lowercase, even if it's an acronym. +* `lowerCamelCase` names capitalize the first letter of each word, *except* + the first which is always lowercase, even if it's an acronym. - `lowerCamelCase` 除了第一个字母始终是小写(即使是缩略词),每个单词的首字母都大写。 + `lowerCamelCase` 除了第一个字母始终是小写(即使是缩略词),每个单词的首字母都大写。 -* `lowercase_with_underscores` names use only lowercase letters, - even for acronyms, - and separate words with `_`. - - `lowercase_with_underscores` 只使用小写字母单词,即使是缩略词, - 并且单词之间使用 `_` 连接。 +* `lowercase_with_underscores` names use only lowercase letters, + even for acronyms, and separate words with `_`. + `lowercase_with_underscores` 只使用小写字母单词,即使是缩略词, + 并且单词之间使用 `_` 连接。 ### DO name types using `UpperCamelCase` @@ -265,20 +263,19 @@ changed for a few reasons: 我们一开始使用 Java `SCREAMING_CAPS` 风格来命名常量。 我们之所以不再使用,是因为: -* `SCREAMING_CAPS` looks bad for many cases, particularly enum values for - things like CSS colors. +* `SCREAMING_CAPS` looks bad for many cases, + particularly enum values for things like CSS colors. - `SCREAMING_CAPS` 很多情况下看起来比较糟糕,尤其类似于 CSS 颜色这类的枚举值。 + `SCREAMING_CAPS` 很多情况下看起来比较糟糕,尤其类似于 CSS 颜色这类的枚举值。 -* Constants are often changed to final non-const variables, which would - necessitate a name change. +* Constants are often changed to final non-const variables, + which would necessitate a name change. - 常量常常被修改为 final 类型的非常量变量,这种情况你还需要修改变量的名字为小写字母形式。 + 常量经常被修改为 final 类型的非常量变量,这种情况你还需要修改变量命名为小写字母形式。 -* The `values` property automatically defined on an enum type is const and - lowercase. +* The `values` property defined on an enum type is const and lowercase. - 在枚举类型中自动定义的 `values` 属性为常量并且是小写字母形式的。 + 在枚举类型中定义的 `values` 属性为常量并且是小写字母形式的。 ::: @@ -288,54 +285,79 @@ changed for a few reasons: ### DO capitalize acronyms and abbreviations longer than two letters like words -### 把超过两个字母的首字母大写缩略词和缩写词当做一般单词来对待。 +### 把超过两个字母的首字母大写缩略词和缩写词当做一般单词来对待 -Capitalized acronyms can be hard to read, and -multiple adjacent acronyms can lead to ambiguous names. -For example, given a name that starts with `HTTPSFTP`, there's no way -to tell if it's referring to HTTPS FTP or HTTP SFTP. +Capitalized acronyms can be hard to read, +and multiple adjacent acronyms can lead to ambiguous names. +For example, given an identifier `HTTPSFTP`, +the reader can't tell if it refers to `HTTPS` `FTP` or `HTTP` `SFTP`. +To avoid this, +capitalize most acronyms and abbreviations like regular words. +This identifier would be `HttpsFtp` if referring to the former +or `HttpSftp` for the latter. 首字母大写缩略词比较难阅读, -特别是多个缩略词连载一起的时候会引起歧义。 -例如,一个以 `HTTPSFTP` 开头的名字, -没有办法判断它是指 HTTPS FTP 还是 HTTP SFTP。 - -To avoid this, acronyms and abbreviations are capitalized like regular words. - -为了避免上面的情况,缩略词和缩写词要像普通单词一样首字母大写。 - -**Exception:** Two-letter *acronyms* like IO (input/output) are fully -capitalized: `IO`. On the other hand, two-letter *abbreviations* like -ID (identification) are still capitalized like regular words: `Id`. - -**例外情况** 两个字母情况下,类似 IO (input/output) 这样的 **缩略词** 要全大写。 -另外,两个字母的 **缩写词** 比如 ID (identification) 与其他常规单词一样, -首字母大写即可: `Id`。 +特别是多个缩略词连在一起的时候会引起歧义。 +例如,一个名为 `HTTPSFTP` 的标识符, +没有办法分辨它是指 `HTTPS` `FTP` 还是 `HTTP` `SFTP`。 +为避免出现这种情况, +大多数缩略词和缩写词都要像普通单词一样大写。 +如果是前者,则应为 `HttpsFtp`, +如果是后者,则应为 `HttpSftp`。 + +Two-letter abbreviations and acronyms are the exception. +If both letters are capitalized in English, +then they should both stay capitalized when used in an identifer. +Otherwise, capitalize it like a word. + +双字母缩写词和首字母缩略词是个例外的情况。 +如果两个字母在英语中都是大写, +那么在标识符中使用时也应该保持大写。 +否则,应该像单词一样首字母大写。 ```dart tag=good -class HttpConnection {} -class DBIOPort {} -class TVVcr {} -class MrRogers {} - -var httpRequest = ... -var uiHandler = ... -var userId = ... -Id id; +// Longer than two letters, so always like a word: +Http // "hypertext transfer protocol" +Nasa // "national aeronautics and space administration" +Uri // "uniform resource locator" +Esq // "esquire" +Ave // "avenue" + +// Two letters, capitalized in English, so capitalized in an identifier: +ID // "identifier" +TV // "television" +UI // "user interface" + +// Two letters, not capitalized in English, so like a word in an identifier: +Mr // "mister" +St // "street" +Rd // "road" ``` ```dart tag=bad -class HTTPConnection {} -class DbIoPort {} -class TvVcr {} -class MRRogers {} - -var hTTPRequest = ... -var uIHandler = ... -var userID = ... -ID iD; +HTTP // "hypertext transfer protocol" +NASA // "national aeronautics and space administration" +URI // "uniform resource locator" +esq // "esquire" +Ave // "avenue" + +Id // "identifier" +Tv // "television" +Ui // "user interface" + +MR // "mister" +ST // "street" +RD // "road" ``` +When any form of abbreviation comes at the beginning +of a lowerCamelCase identifier, lowercase the identifer: + +```dart +var httpConnection = connect(); +var tvSet = Television(); +var mrRogers = 'hello, neighbor'; +``` ### PREFER using `_`, `__`, etc. for unused callback parameters diff --git a/src/content/get-dart/index.md b/src/content/get-dart/index.md index 7034df4f3..65b40e89c 100644 --- a/src/content/get-dart/index.md +++ b/src/content/get-dart/index.md @@ -13,6 +13,11 @@ you need to develop Dart command-line, server, and web apps. To learn more about the Dart SDK, consult the [Dart SDK overview](/tools/sdk). +:::tip +If you've installed or plan to [install the Flutter SDK][install-flutter], it +includes the full Dart SDK. You don't need to install Dart separately and can skip this guide. +::: + ## System requirements Dart supports the following hardware architectures and platform versions diff --git a/src/content/guides/language/index.md b/src/content/guides/language/index.md index f5096ab59..ca00de863 100644 --- a/src/content/guides/language/index.md +++ b/src/content/guides/language/index.md @@ -30,9 +30,9 @@ These two resources are popular with both beginning Dart developers and experts. * [Customizing static analysis](/tools/analysis)
A guide to customizing the analyzer using an analysis options file. * Asynchronous programming - * [Futures, async, await](/codelabs/async-await)
+ * [Futures, async, await](/libraries/async/async-await)
Learn about and practice writing asynchronous code, using DartPad. - * [Streams](/tutorials/language/streams)
+ * [Streams](/libraries/async/using-streams)
A beginner's guide to handling sequences of asynchronous events. * [Specification](/guides/language/spec)
A definitive, highly technical description of the Dart language. diff --git a/src/content/guides/whats-new.md b/src/content/guides/whats-new.md index 5e3a6cedd..d1ad575fb 100644 --- a/src/content/guides/whats-new.md +++ b/src/content/guides/whats-new.md @@ -579,7 +579,7 @@ we made the following changes to this site: * Introduced a new section to the language tour documenting [initializing formal parameters][]. * Documented DartPad's [support for packages][]. - * Fixed formatting in the [asynchronous programming codelab][] + * Fixed formatting in the [asynchronous programming tutorial][] and elaborated on [why asynchronous code matters][]. * Updated the [security][] page to match our current security practices. * Added a key binding (`/`) to automatically focus the search bar. @@ -621,8 +621,8 @@ we made the following changes to this site: [native types]: /interop/c-interop#interface-with-native-types [initializing formal parameters]: /language/constructors#use-initializing-formal-parameters [support for packages]: /tools/dartpad#library-support -[asynchronous programming codelab]: /codelabs/async-await -[why asynchronous code matters]: /codelabs/async-await#why-asynchronous-code-matters +[asynchronous programming tutorial]: /libraries/async/async-await +[why asynchronous code matters]: /libraries/async/async-await#why-asynchronous-code-matters [security]: /security @@ -851,7 +851,7 @@ we made the following changes to this site: [HTTP server tutorial]: /tutorials/server/httpserver [`lints`]: {{site.pub-pkg}}/lints [Numbers in Dart]: /guides/language/numbers -[streams tutorial]: /tutorials/language/streams +[streams tutorial]: /libraries/async/using-streams [typedef section]: /language/typedefs [Using Google APIs]: /resources/google-apis [Using Google Cloud]: /server/google-cloud @@ -895,7 +895,7 @@ In addition to bug fixes and incremental improvements, we made the following cha * Updated the [language evolution page][evolution] to add information about language versioning and to reflect Dart 2.12. -* Updated the [library tour][] and [codelabs][] +* Updated the [library tour][] and [tutorials][] to reflect sound null safety. * Updated pages across the site to use [the `dart` tool][] instead of deprecated commands. @@ -918,7 +918,7 @@ We also switched from Travis CI to GitHub Actions, and we made multiple CSS chan [language tour]: /language [`late` variables]: /language/variables#late-variables [library tour]: /libraries -[codelabs]: /codelabs +[tutorials]: /tutorials [the `dart` tool]: /tools/dart-tool [`dart analyze`]: /tools/dart-analyze [`dart compile`]: /tools/dart-compile diff --git a/src/content/index.html b/src/content/index.html index 65b18c932..56d6b3b0b 100644 --- a/src/content/index.html +++ b/src/content/index.html @@ -104,7 +104,7 @@
为基于事件驱动的用户界面提供成熟且完备的 - 异步-等待 体系, + 异步-等待 体系, 同时配备了 基于 isolate 的并发
@@ -264,7 +264,7 @@
为基于事件驱动的用户界面提供成熟且完备的 - 异步-等待 体系, + 异步-等待 体系, 同时配备了 基于 isolate 的并发
diff --git a/src/content/language/async.md b/src/content/language/async.md index 3c06bc8d1..c7b737a8d 100644 --- a/src/content/language/async.md +++ b/src/content/language/async.md @@ -31,7 +31,7 @@ When you need the result of a completed Future, you have two options: * Use `async` and `await`, as described here and in the - [asynchronous programming codelab](/codelabs/async-await). + [asynchronous programming tutorial](/libraries/async/async-await). * Use the Future API, as described in the [`dart:async` documentation](/libraries/dart-async#future). @@ -117,7 +117,7 @@ use the [unawaited_futures linter rule][]. ::: For an interactive introduction to using futures, `async`, and `await`, -see the [asynchronous programming codelab](/codelabs/async-await). +see the [asynchronous programming tutorial](/libraries/async/async-await). ## Declaring async functions @@ -149,7 +149,7 @@ If your function doesn't return a useful value, make its return type `Future`. For an interactive introduction to using futures, `async`, and `await`, -see the [asynchronous programming codelab](/codelabs/async-await). +see the [asynchronous programming tutorial](/libraries/async/async-await). {% comment %} TODO #1117: Where else should we cover generalized void? diff --git a/src/content/language/class-modifiers.md b/src/content/language/class-modifiers.md index 3c5c47e55..cf7587483 100644 --- a/src/content/language/class-modifiers.md +++ b/src/content/language/class-modifiers.md @@ -80,7 +80,11 @@ Vehicle myVehicle = Vehicle(); // Can be extended. class Car extends Vehicle { int passengers = 4; - // ··· + + @override + void moveForward(int meters) { + // ... + } } // Can be implemented. diff --git a/src/content/language/concurrency.md b/src/content/language/concurrency.md index 396e845ee..c4bb3d59b 100644 --- a/src/content/language/concurrency.md +++ b/src/content/language/concurrency.md @@ -224,9 +224,9 @@ Stream sumStream(Stream stream) async* { ``` If you'd like to learn more about using `async`, `await`, `Stream`s and -`Future`s, visit the [asynchronous programming codelab][]. +`Future`s, check out the [asynchronous programming tutorial][]. -[asynchronous programming codelab]: /codelabs/async-await +[asynchronous programming tutorial]: /libraries/async/async-await ## Isolates @@ -280,7 +280,7 @@ complete. A well-behaved app starts quickly, getting to the event loop as soon as possible. The app then responds to each queued event promptly, using asynchronous operations as necessary. -[async-await]: /codelabs/async-await +[async-await]: /libraries/async/async-await ### The isolate life cycle diff --git a/src/content/language/functions.md b/src/content/language/functions.md index 768e5ebe9..2c14ab131 100644 --- a/src/content/language/functions.md +++ b/src/content/language/functions.md @@ -49,7 +49,7 @@ The => expr syntax is a shorthand for is sometimes referred to as _arrow_ syntax. :::note -Only _expressions_ can appear between the arrow (`=\>`) and the semicolon (`;`). +Only _expressions_ can appear between the arrow (`=>`) and the semicolon (`;`). Expressions evaluate to values. This means that you can't write a statement where Dart expects a value. For example, @@ -204,8 +204,9 @@ String say(String from, String msg, [String device = 'carrier pigeon']) { assert(say('Bob', 'Howdy') == 'Bob says Howdy with a carrier pigeon'); ``` + -## The main() function +## The main() function {:#main} Every app must have a top-level `main()` function, which serves as the entrypoint to the app. The `main()` function returns `void` and has an diff --git a/src/content/language/index.md b/src/content/language/index.md index 20946b86d..fe7e2718b 100644 --- a/src/content/language/index.md +++ b/src/content/language/index.md @@ -23,11 +23,11 @@ listed under **Language** in the left side menu. For coverage of Dart's core libraries, check out the [core library documentation](/libraries). -You can also try the [Dart cheatsheet codelab](/codelabs/dart-cheatsheet), -for a more hands-on introduction. +You can also check out the [Dart cheatsheet](/resources/dart-cheatsheet), +for a more interactive introduction. 想要了解 Dart 的核心库,访问 [核心库文档](/libraries)。 -你也可以查看 [Dart 语言的速查表 CodeLab](/codelabs/dart-cheatsheet), +你也可以查看 [Dart 语言的速查表](/resources/dart-cheatsheet), 来获得一些快速上手的指导。 ## Hello World diff --git a/src/content/language/loops.md b/src/content/language/loops.md index c0c150bd5..2b998f7bd 100644 --- a/src/content/language/loops.md +++ b/src/content/language/loops.md @@ -74,7 +74,7 @@ for (final Candidate(:name, :yearsExperience) in candidates) { :::tip To practice using `for-in`, follow the -[Iterable collections codelab](/codelabs/iterables). +[Iterable collections tutorial](/libraries/collections/iterables). ::: Iterable classes also have a [forEach()][] method as another option: diff --git a/src/content/language/mixins.md b/src/content/language/mixins.md index ab047e8e0..a9dd3876e 100644 --- a/src/content/language/mixins.md +++ b/src/content/language/mixins.md @@ -96,7 +96,7 @@ class Virtuoso with Musician { #### Access state in the mixin's subclass -Declaring abstract memebers also allows you to access state on the subclass +Declaring abstract members also allows you to access state on the subclass of a mixin, by calling getters which are defined as abstract on the mixin: ```dart diff --git a/src/content/language/pattern-types.md b/src/content/language/pattern-types.md index f0bb32129..a0fa85c34 100644 --- a/src/content/language/pattern-types.md +++ b/src/content/language/pattern-types.md @@ -279,7 +279,7 @@ pattern where a higher precedence one is expected. For example, imagine the boolean constants `x`, `y`, and `z` equal `true`, `true`, and `false`, respectively. -Though the following example resembles boolean expression evaulation, +Though the following example resembles boolean expression evaluation, the example matches patterns. diff --git a/src/content/language/patterns.md b/src/content/language/patterns.md index 78ef57f40..12a1925c1 100644 --- a/src/content/language/patterns.md +++ b/src/content/language/patterns.md @@ -303,6 +303,14 @@ as its subpattern: var (name, age) = userInfo(json); ``` +To destructure a record with named fields using a pattern: + + +```dart +final (:name, :age) = + getData(); // For example, return (name: 'doug', age: 25); +``` + ### Destructuring class instances [Object patterns][object] match against named object types, allowing diff --git a/src/content/codelabs/async-await.md b/src/content/libraries/async/async-await.md similarity index 98% rename from src/content/codelabs/async-await.md rename to src/content/libraries/async/async-await.md index 7f272f4a6..fd72b9520 100644 --- a/src/content/codelabs/async-await.md +++ b/src/content/libraries/async/async-await.md @@ -8,32 +8,32 @@ js: [{url: '/assets/js/inject_dartpad.js', defer: true}] -This codelab teaches you how to write asynchronous code using +This tutorial teaches you how to write asynchronous code using futures and the `async` and `await` keywords. Using embedded DartPad editors, you can test your knowledge by running example code and completing exercises. -To get the most out of this codelab, you should have the following: +To get the most out of this tutorial, you should have the following: * Knowledge of [basic Dart syntax](/language). * Some experience writing asynchronous code in another language. -This codelab covers the following material: +This tutorial covers the following material: * How and when to use the `async` and `await` keywords. * How using `async` and `await` affects execution order. * How to handle errors from an asynchronous call using `try-catch` expressions in `async` functions. -Estimated time to complete this codelab: 40-60 minutes. +Estimated time to complete this tutorial: 40-60 minutes. :::note This page uses embedded DartPads to display examples and exercises. {% render 'dartpads-embedded-troubleshooting.md' %} ::: -The exercises in this codelab have partially completed code snippets. +The exercises in this tutorial have partially completed code snippets. You can use DartPad to test your knowledge by completing the code and clicking the **Run** button. **Don't edit the test code in the `main` function or below**. @@ -1080,13 +1080,13 @@ bool _logoutSucceeds = false; ## What's next? -Congratulations, you've finished the codelab! If you'd like to learn more, here +Congratulations, you've finished the tutorial! If you'd like to learn more, here are some suggestions for where to go next: - Play with [DartPad]({{site.dartpad}}). -- Try another [codelab](/codelabs). +- Try another [tutorial](/tutorials). - Learn more about futures and asynchronous code in Dart: - - [Streams tutorial](/tutorials/language/streams): + - [Streams tutorial](/libraries/async/using-streams): Learn how to work with a sequence of asynchronous events. - [Concurrency in Dart](/language/concurrency): Understand and learn how to implement concurrency in Dart. diff --git a/src/content/libraries/async/futures-error-handling.md b/src/content/libraries/async/futures-error-handling.md index 50b03ecf4..67839116c 100644 --- a/src/content/libraries/async/futures-error-handling.md +++ b/src/content/libraries/async/futures-error-handling.md @@ -22,7 +22,7 @@ You don't need this page if your code uses the language's asynchrony support: `async`, `await`, and error handling using try-catch. For more information, see the -[asynchronous programming codelab](/codelabs/async-await). +[asynchronous programming tutorial](/libraries/async/async-await). ::: diff --git a/src/content/codelabs/iterables.md b/src/content/libraries/collections/iterables.md similarity index 98% rename from src/content/codelabs/iterables.md rename to src/content/libraries/collections/iterables.md index a3b5573bf..606f9ca3d 100644 --- a/src/content/codelabs/iterables.md +++ b/src/content/libraries/collections/iterables.md @@ -1,44 +1,45 @@ --- # title: Iterable collections title: 可迭代集合 -# description: An interactive guide to using Iterable objects such as lists and sets. +# description: >- +# An interactive guide to using Iterable objects such as lists and sets. description: 可迭代对象(例如列表和集合)的交互式指南 js: [{url: '/assets/js/inject_dartpad.js', defer: true}] --- -This codelab teaches you how to use collections that +This tutorial teaches you how to use collections that implement the [Iterable][iterable class] class—for example [List][list class] and [Set.][set class] Iterables are basic building blocks for all sorts of Dart applications, and you're probably already using them, even without noticing. -This codelab helps you make the most out of them. +This tutorial helps you make the most out of them. Using the embedded DartPad editors, you can test your knowledge by running example code and completing exercises. -To get the most out of this codelab, +To get the most out of this tutorial, you should have basic knowledge of [Dart syntax](/language). -This codelab covers the following material: +This tutorial covers the following material: * How to read elements of an Iterable. * How to check if the elements of an Iterable satisfy a condition. * How to filter the contents of an Iterable. * How to map the contents of an Iterable to a different value. -Estimated time to complete this codelab: 60 minutes. +Estimated time to complete this tutorial: 60 minutes. :::note This page uses embedded DartPads to display examples and exercises. {% render 'dartpads-embedded-troubleshooting.md' %} ::: -The exercises in this codelab have partially completed code snippets. +The exercises in this tutorial have partially completed code snippets. You can use DartPad to test your knowledge by completing the code and clicking the **Run** button. **Don't edit the test code in the `main` function or below**. @@ -1213,14 +1214,14 @@ bool isValidEmailAddress(EmailAddress email) { ## What's next -Congratulations, you finished the codelab! +Congratulations, you finished the tutorial! If you want to learn more, here are some suggestions for where to go next: * Play with [DartPad.]({{site.dartpad}}) -* Try another [codelab](/codelabs). +* Try another [tutorial](/tutorials). * Read the [Iterable API reference][iterable class] - to learn about methods not covered by this codelab. + to learn about methods that this tutorial doesn't cover. [hashmap class]: {{site.dart-api}}/{{site.sdkInfo.channel}}/dart-collection/HashMap-class.html [iterable class]: {{site.dart-api}}/{{site.sdkInfo.channel}}/dart-core/Iterable-class.html diff --git a/src/content/libraries/dart-async.md b/src/content/libraries/dart-async.md index f0463b72a..45c45af49 100644 --- a/src/content/libraries/dart-async.md +++ b/src/content/libraries/dart-async.md @@ -23,7 +23,7 @@ dart:async library ([API reference][dart:async]). You don't always need to use the Future or Stream APIs directly. The Dart language supports asynchronous coding using keywords such as `async` and `await`. -Check out the [asynchronous programming codelab](/codelabs/async-await) +Check out the [asynchronous programming tutorial](/libraries/async/async-await) for details. ::: @@ -101,7 +101,7 @@ function from your function. ::: For more information on using `await` and related Dart language features, -see the [asynchronous programming codelab](/codelabs/async-await). +see the [asynchronous programming tutorial](/libraries/async/async-await). ### Basic usage @@ -342,7 +342,7 @@ DOM event listeners in a row, then the second kind of event is never handled. For more information on using `await` and related Dart language features, see the -[asynchronous programming codelab](/codelabs/async-await). +[asynchronous programming tutorial](/libraries/async/async-await). ### Listening for stream data @@ -453,11 +453,11 @@ inputStream.transform(utf8.decoder).transform(const LineSplitter()).listen( For some examples of using Future and Stream in command-line apps, check out the [dart:io documentation][]. -Also see these articles, codelabs, and tutorials: +Also see these articles and tutorials: -- [Asynchronous programming: futures, async, await](/codelabs/async-await) +- [Asynchronous programming: futures, async, await](/libraries/async/async-await) - [Futures and error handling](/libraries/async/futures-error-handling) -- [Asynchronous programming: streams](/tutorials/language/streams) +- [Asynchronous programming: streams](/libraries/async/using-streams) - [Creating streams in Dart](/libraries/async/creating-streams) - [Dart asynchronous programming: Isolates and event loops](/language/concurrency) diff --git a/src/content/libraries/dart-core.md b/src/content/libraries/dart-core.md index fbcbb5f02..7c34b4825 100644 --- a/src/content/libraries/dart-core.md +++ b/src/content/libraries/dart-core.md @@ -299,7 +299,7 @@ lists, sets, and maps. :::tip To practice using APIs that are available to both lists and sets, -follow the [Iterable collections codelab](/codelabs/iterables). +follow the [Iterable collections tutorial](/libraries/collections/iterables). ::: ### Lists @@ -947,7 +947,7 @@ void main() { The [Iterable][] and [Iterator][] classes support sequential access to a collection of values. To practice using these collections, -follow the [Iterable collections codelab](/codelabs/iterables). +follow the [Iterable collections tutorial](/libraries/collections/iterables). If you create a class that can provide Iterators for use in for-in loops, extend (if possible) or implement Iterable. diff --git a/src/content/null-safety/index.md b/src/content/null-safety/index.md index 0f103c9fa..65ce63c15 100644 --- a/src/content/null-safety/index.md +++ b/src/content/null-safety/index.md @@ -85,10 +85,10 @@ int? aNullableInt = null; - To try some interactive examples, try out some of the null-safety orientated examples in the - [Dart cheatsheet](/codelabs/dart-cheatsheet). + [Dart cheatsheet](/resources/dart-cheatsheet). 要尝试一些交互示例, - 请查看 [Dart 语言的速查表 CodeLab](/codelabs/dart-cheatsheet) 中 + 请查看 [Dart 语言的速查表](/resources/dart-cheatsheet) 中 一些面向空安全的示例。 - To learn more about null safety, check out diff --git a/src/content/resources/breaking-changes.md b/src/content/resources/breaking-changes.md index 093485659..14110681b 100644 --- a/src/content/resources/breaking-changes.md +++ b/src/content/resources/breaking-changes.md @@ -3,6 +3,11 @@ title: Breaking changes and deprecations description: A list of breaking changes by release in Dart. --- +{% assign versioned = 'Language versioned' %} +{% assign deprecated = 'Deprecated' %} +{% assign removed = 'Removed' %} +{% assign experimental = 'Experimental' %} + This page lists all language and library breaking changes and deprecations in Dart, organized by release and area, to help Dart users understand and manage their impact. Complete release notes are available in the [Dart SDK changelog][changelog]. @@ -20,20 +25,19 @@ around breaking changes and deprecations in Dart. existing code, and the behavior change only takes effect (potentially breaking code that relies on the previous behavior) when you upgrade the [language version][] of your code. - - - _These are marked "**Language versioned**"_. + + _These are marked as:_ {{versioned}} * **Deprecations**: The Dart SDK maintains compatibility for deprecated code, with a warning. Deprecations are then completely removed in a subsequent release, breaking any code that relies on the previous behavior. - - _These are marked "**Deprecated**" and "**Removed**", respectively_. + + _These are marked as:_ {{deprecated}} / {{removed}} * **Experimental**: Part of the release but not yet treated as stable in the SDK, and can break from one version to another. Experimental changes do not always have a corresponding breaking change issue, but may have more detail in the [SDK changelog][changelog]. - _These are marked "**Experimental**", possibly in conjunction with another change type_. + These are marked: {{experimental}} If you have questions or concerns about any of these breaking changes, please comment on the breaking change issue linked from the relevant entry. @@ -86,14 +90,14 @@ accounting for them before the 3.5.0 release. #### `dart:typed_data` -- **Removed**: +- {{removed}} [The unmodifiable view classes for typed data have been removed][53128]. Instead of using the constructors of these classes, use the new `asUnmodifiableView` methods on typed data lists. ### Runtime {:.no_toc} -- **Removed** The Dart VM no longer supports unsound null safety. +- {{removed}} The Dart VM no longer supports unsound null safety. - The `--no-sound-null-safety` CLI option has been removed. - The `Dart_NewListOf` and `Dart_IsLegacyType` functions have been removed from the C API. @@ -116,14 +120,14 @@ accounting for them before the 3.5.0 release. #### `dart:cli` -- **Experimental** **Removed**: [The `waitFor` function][52121] +- {{experimental}} {{removed}} [The `waitFor` function][52121] has been removed. [52121]: {{site.repo.dart.sdk}}/issues/52121 #### `dart:html`, `dart:indexed:db`, `dart:svg`, `dart:web_audo`, `dart:web_gl` -- These libraries are now marked as legacy and +- {{deprecated}} These libraries are now marked as legacy and will see less support in the future. New projects should prefer to use [`package:web`][] and `dart:js_interop`. To learn more, check out [Migrate to package:web][]. @@ -133,7 +137,8 @@ accounting for them before the 3.5.0 release. #### `dart:js` -- This library is now marked as legacy and will see less support in the future. +- {{deprecated}} + This library is now marked as legacy and will see less support in the future. Usages should be migrated to `dart:js_interop` and `dart:js_interop_unsafe`. To learn more, check out [`/go/next-gen-js-interop`][]. @@ -141,7 +146,8 @@ accounting for them before the 3.5.0 release. #### `dart:js_util` -- This library is now marked as legacy and will see less support in the future. +- {{deprecated}} + This library is now marked as legacy and will see less support in the future. Usages should be migrated to `dart:js_interop` and `dart:js_interop_unsafe`. To learn more, check out [`/go/next-gen-js-interop`][]. @@ -153,14 +159,14 @@ accounting for them before the 3.5.0 release. developers to control the line ending used by `stdout` and `stderr`.][53863] Classes that implement `Stdout` must define the `lineTerminator` field. The default semantics of `stdout` and `stderr` are not changed. -- **Deprecated**: The `FileSystemDeleteEvent.isDirectory` property. +- {{deprecated}} The `FileSystemDeleteEvent.isDirectory` property. It always returns `false`. [53863]: {{site.repo.dart.sdk}}/issues/53863 #### `dart:typed_data` -- **Deprecated**: +- {{deprecated}} [The unmodifiable view classes for typed data are deprecated][53128]. Instead of using the constructors of these classes, use the new `asUnmodifiableView` methods on typed data lists. @@ -171,19 +177,19 @@ accounting for them before the 3.5.0 release. #### Production JavaScript compiler (dart2js) -- **Experimental** **Deprecated**: You should now specify a format to +- {{experimental}} {{deprecated}} You should now specify a format to the `--dump-info` CLI option of either `binary` or `json`. The `json` format is deprecated and might be removed in a future Dart release. #### Wasm compiler (dart2wasm) -- **Experimental**: Various `dart compile wasm` CLI arguments have +- {{experimental}} Various `dart compile wasm` CLI arguments have been updated, removed, or replaced. To learn more, run `dart compile wasm --verbose --help`. ### Runtime {:.no_toc} -- **Removed** The Dart VM longer supports external strings. +- {{removed}} The Dart VM longer supports external strings. As a result, the `Dart_IsExternalString`, `Dart_NewExternalLatin1String`, and `Dart_NewExternalUTF16String` functions have been removed from the Dart C API. @@ -191,7 +197,7 @@ accounting for them before the 3.5.0 release. ### SDK {:.no_toc} -* **Experimental** **Removed**: The following experiments are now retired as +* {{experimental}} {{removed}} The following experiments are now retired as they were released in Dart 3 and are no longer necessary with a language version of 3.0 or greater. Configuration of them should be removed from @@ -213,17 +219,17 @@ accounting for them before the 3.5.0 release. #### `dart:cli` -* **Experimental** **Deprecated**: [The `waitFor` function][52121] +* {{experimental}} {{deprecated}} [The `waitFor` function][52121] remains deprecated for another release and is set for removal in Dart 3.4. [52121]: {{site.repo.dart.sdk}}/issues/52121 #### `dart:ffi` -* **Deprecated**: [The `elementAt` pointer arithmetic methods +* {{deprecated}} [The `elementAt` pointer arithmetic methods on `Pointer` types are deprecated][54250]. Migrate to the `-` and `+` operators instead. -* **Experimental** **Removed**: The previously deprecated +* {{experimental}} {{removed}} The previously deprecated `@FfiNative` annotation has been removed. Usages should be updated to use the `@Native` annotation. @@ -245,14 +251,14 @@ accounting for them before the 3.5.0 release. #### `dart:js_interop` -* **Experimental**: JS types like `JSAny` have +* {{experimental}} JS types like `JSAny` have [new compiler-specific representation types][52687]. -* **Experimental**: User-defined `@staticInterop` classes can +* {{experimental}} User-defined `@staticInterop` classes can [no longer implement `JSAny` or `JSObject`][52687]. Usages should be migrated to `JSObject.fromInteropObject` or be defined as extension types. -* **Experimental**: `JSArray` and `JSPromise` now have generic parameters. -* **Experimental**: Various extension members were moved or renamed. +* {{experimental}} `JSArray` and `JSPromise` now have generic parameters. +* {{experimental}} Various extension members were moved or renamed. To learn about the updated extensions, reference `JSAnyUtilityExtension` and `JSAnyOperatorExtension`. @@ -269,7 +275,7 @@ accounting for them before the 3.5.0 release. #### `dart:nativewrappers` -* **Experimental**: [All native wrapper classes are now marked `base`][51896] +* {{experimental}} [All native wrapper classes are now marked `base`][51896] so that none of their subtypes can be implemented. [51896]: {{site.repo.dart.sdk}}/issues/51896 @@ -285,14 +291,14 @@ accounting for them before the 3.5.0 release. #### Wasm compiler (dart2wasm) -* **Experimental**: [Disallow importing legacy JS interop libraries][54004]. +* {{experimental}} [Disallow importing legacy JS interop libraries][54004]. Prefer using `dart:js_interop` and `dart:js_interop_unsafe` instead. [54004]: {{site.repo.dart.sdk}}/issues/54004 #### Analyzer -* **Experimental**: Invalid `dart doc` comment directives are +* {{experimental}} Invalid `dart doc` comment directives are now reported by the analyzer. * Due to [improvements in type promotion][54056], the following analyzer diagnostics might trigger on existing code that previously passed analysis: @@ -323,7 +329,7 @@ accounting for them before the 3.5.0 release. ### Language {:.no_toc} -* **Language versioned**: [Changed the split point for refutable patterns][53167] +* {{versioned}} [Changed the split point for refutable patterns][53167] to the top level pattern so type promotion in if-case statements is consistent regardless of whether the scrutinee might throw an exception. @@ -331,7 +337,7 @@ accounting for them before the 3.5.0 release. #### `dart:cli` -* **Experimental** **Deprecated**: [The `waitFor` function.][52121] +* {{experimental}} {{deprecated}} [The `waitFor` function.][52121] #### `dart:convert` @@ -340,7 +346,7 @@ accounting for them before the 3.5.0 release. #### `dart:developer` -* **Deprecated**: The `Service.getIsolateID` method. +* {{deprecated}} The `Service.getIsolateID` method. #### `dart:ffi` @@ -355,18 +361,18 @@ accounting for them before the 3.5.0 release. #### `dart:js_interop` -* **Experimental** **Removed**: `JSNumber.toDart` in favor of `toDartDouble` and +* {{experimental}} {{removed}} `JSNumber.toDart` in favor of `toDartDouble` and `toDartInt`. -* **Experimental** **Removed**: `Object.toJS` in favor of `Object.toJSBox.` -* **Experimental**: Restricted external JS interop APIs using `dart:js_interop` +* {{experimental}} {{removed}} `Object.toJS` in favor of `Object.toJSBox.` +* {{experimental}} Restricted external JS interop APIs using `dart:js_interop` to a set of allowed types. -* **Experimental**: Prohibited use of `isNull` and `isUndefined` on dart2wasm. -* **Experimental**: Changed `typeofEquals` and `instanceof` APIs to both return +* {{experimental}} Prohibited use of `isNull` and `isUndefined` on dart2wasm. +* {{experimental}} Changed `typeofEquals` and `instanceof` APIs to both return bool instead of `JSBoolean`. Also, `typeofEquals` now takes `String` instead of `JSString`. -* **Experimental**: Changed `JSAny` and `JSObject` types to only implementable, +* {{experimental}} Changed `JSAny` and `JSObject` types to only implementable, not extendable, by user `@staticInterop` types. -* **Experimental**: Changed `JSArray.withLength` to take `int` instead of `JSNumber`. +* {{experimental}} Changed `JSArray.withLength` to take `int` instead of `JSNumber`. ### Tools {:.no_toc} @@ -382,7 +388,7 @@ accounting for them before the 3.5.0 release. #### Analyzer -* **Language versioned**: [Private final field promotion][2020] might cause the following +* {{versioned}} [Private final field promotion][2020] might cause the following analyzer warnings to trigger on existing code that previously passed analysis: * [`unnecessary_non_null_assertion`](/tools/diagnostic-messages#unnecessary_non_null_assertion) @@ -432,7 +438,7 @@ accounting for them before the 3.5.0 release. #### `dart:js_interop` -* **Experimental** **Removed**: `ObjectLiteral`; create an object literal with +* {{experimental}} {{removed}} `ObjectLiteral`; create an object literal with no named members using `{}.jsify()`. #### `package:js` @@ -456,10 +462,10 @@ on all the changes in this section. ### Language {:.no_toc} -* **Language versioned**: Changed interpretation of [switch cases] from constant +* {{versioned}} Changed interpretation of [switch cases] from constant expressions to patterns. -* **Language versioned**: Class declarations from libraries that have been upgraded +* {{versioned}} Class declarations from libraries that have been upgraded to Dart 3.0 [can no longer be used as mixins by default][mixin class]. * [Dart reports a compile-time error][50902] if a `continue` statement targets @@ -474,36 +480,36 @@ on all the changes in this section. #### `dart:core` -* **Deprecated**: [Deprecated APIs][49529]. +* {{deprecated}} [Deprecated APIs][49529]. #### `dart:async` -* **Removed**: [Removed the deprecated][49529] [`DeferredLibrary`][] class. +* {{removed}} [Removed the deprecated][49529] [`DeferredLibrary`][] class. #### `dart:collection` -* **Language versioned**: [Changes to platform libraries][collection]. +* {{versioned}} [Changes to platform libraries][collection]. #### `dart:developer` -* **Removed**: [Removed the deprecated][49529] [`MAX_USER_TAGS`][] constant. +* {{removed}} [Removed the deprecated][49529] [`MAX_USER_TAGS`][] constant. Use [`maxUserTags`][] instead. -* **Removed**: [Removed the deprecated][50231] [`Metrics`][], [`Metric`][], [`Counter`][], +* {{removed}} [Removed the deprecated][50231] [`Metrics`][], [`Metric`][], [`Counter`][], and [`Gauge`][] classes as they have been broken since Dart 2.0. #### `dart:ffi` -* **Experimental** **Deprecated**: The `@FfiNative` annotation is +* {{experimental}} {{deprecated}} The `@FfiNative` annotation is now deprecated. Usages should be updated to use the `@Native` annotation. #### `dart:html` -* **Removed**: [Removed the deprecated `registerElement` and `registerElement2`][49536] +* {{removed}} [Removed the deprecated `registerElement` and `registerElement2`][49536] methods in `Document` and `HtmlDocument`. #### `dart:math` -* **Language versioned**: The `Random` interface can only be implemented, +* {{versioned}} The `Random` interface can only be implemented, not extended. #### `dart:io` @@ -544,12 +550,12 @@ on all the changes in this section. #### `dart:convert` -* **Removed**: [The previously deprecated API][34233] [`DEFAULT_BUFFER_SIZE`] in `JsonUtf8Encoder` +* {{removed}} [The previously deprecated API][34233] [`DEFAULT_BUFFER_SIZE`] in `JsonUtf8Encoder` has been removed. #### `dart:developer` -* **Removed**: [Removed previously deprecated APIs][34233] `kInvalidParams`, +* {{removed}} [Removed previously deprecated APIs][34233] `kInvalidParams`, `kExtensionError`, `kExtensionErrorMax`, and `kExtensionErrorMin` in [`ServiceExtensionResponse`]. @@ -575,7 +581,7 @@ on all the changes in this section. #### `dart:mirrors` -* [Removed APIs][34233] [`MirrorsUsed`] and [`Comment`]. +* {{removed}} [Removed APIs][34233] `MirrorsUsed` and `Comment`. #### `package:js` @@ -658,9 +664,9 @@ on all the changes in this section. #### Dart command line -* **Deprecated**: [Deprecated the standalone `dart2js` tool][46100]. -* **Deprecated**: [Deprecated the standalone `dartdevc` tool][46100]. -* **Removed**: [Removed the standalone `dartdoc` tool][46100]. +* {{deprecated}} [Deprecated the standalone `dart2js` tool][46100]. +* {{deprecated}} [Deprecated the standalone `dartdevc` tool][46100]. +* {{removed}} [Removed the standalone `dartdoc` tool][46100]. [47887]: {{site.repo.dart.sdk}}/issues/47887 [48093]: {{site.repo.dart.sdk}}/issues/48093 @@ -676,19 +682,19 @@ on all the changes in this section. * On Windows, [`Directory.rename` will no longer delete a directory][47653] if `newPath` specifies one. Instead, a `FileSystemException` will be thrown. -* **Removed**: [Removed the `Platform.packageRoot` API][47769]. +* {{removed}} [Removed the `Platform.packageRoot` API][47769]. #### `dart:isolate` -* **Removed**: [Removed the `Isolate.packageRoot` API][47769]. +* {{removed}} [Removed the `Isolate.packageRoot` API][47769]. ### Tools {:.no_toc} #### Dart command line -* **Deprecated**: [Deprecated the standalone `dartanalyzer` tool][46100]. -* **Deprecated**: [Deprecated the standalone `dartdoc` tool][46100]. -* **Removed**: [Removed the deprecated standalone `pub` tool][46100]. +* {{deprecated}} [Deprecated the standalone `dartanalyzer` tool][46100]. +* {{deprecated}} [Deprecated the standalone `dartdoc` tool][46100]. +* {{removed}} [Removed the deprecated standalone `pub` tool][46100]. [47653]: {{site.repo.dart.sdk}}/issues/47653 [47769]: {{site.repo.dart.sdk}}/issues/47769 diff --git a/src/content/resources/coming-from/js-to-dart.md b/src/content/resources/coming-from/js-to-dart.md index ad5b76ffb..b11646d1a 100644 --- a/src/content/resources/coming-from/js-to-dart.md +++ b/src/content/resources/coming-from/js-to-dart.md @@ -1805,9 +1805,9 @@ Future asyncFunction() async { To learn more about `Future`s and the `async`/`await` syntax, see the -[Asynchronous programming][] codelab. +[Asynchronous programming][] tutorial. -[Asynchronous programming]: /codelabs/async-await +[Asynchronous programming]: /libraries/async/async-await ### Streams @@ -1963,7 +1963,7 @@ Learn more about futures, streams, and other asynchronous functionality in the [asynchronous programming][] docs. -[asynchronous programming]: /tutorials/language/streams +[asynchronous programming]: /libraries/async/using-streams ## Classes @@ -2775,11 +2775,11 @@ Some possible next steps: * [Language tour][] to learn more about the Dart language * [Core library documentation][] to learn about Dart's core libraries -* [Dart codelabs][] for hands-on experience learning a variety of topics +* [Dart tutorials][] for applied practice covering a variety of topics * [Effective Dart][] to learn about common conventions and guidelines when writing Dart code [Language tour]: /language [Core library documentation]: /libraries -[Dart codelabs]: /codelabs +[Dart tutorials]: /tutorials [Effective Dart]: /effective-dart diff --git a/src/content/resources/coming-from/swift-to-dart.md b/src/content/resources/coming-from/swift-to-dart.md index bb3a6a508..0ee1de50e 100644 --- a/src/content/resources/coming-from/swift-to-dart.md +++ b/src/content/resources/coming-from/swift-to-dart.md @@ -2558,10 +2558,10 @@ Future asyncFunction() async { } ``` -For more information and some hands-on practice, -check out the [Asynchronous programming][] codelab. +For more information and interactive practice, +check out the [Asynchronous programming][] tutorial. -[Asynchronous programming]: /codelabs/async-await +[Asynchronous programming]: /libraries/async/async-await ### Streams diff --git a/src/content/codelabs/dart-cheatsheet.md b/src/content/resources/dart-cheatsheet.md similarity index 92% rename from src/content/codelabs/dart-cheatsheet.md rename to src/content/resources/dart-cheatsheet.md index 8750117f5..d3c76ef66 100644 --- a/src/content/codelabs/dart-cheatsheet.md +++ b/src/content/resources/dart-cheatsheet.md @@ -1,6 +1,6 @@ --- -# title: Dart cheatsheet codelab -title: Dart 速查表 codelab +# title: Dart cheatsheet +title: Dart 速查表 # description: Interactively learn (or relearn) some of Dart's unique features. description: 用交互的形式学习(或回顾)Dart 的独特之处。 js: [{url: '/assets/js/inject_dartpad.js', defer: true}] @@ -10,7 +10,7 @@ js: [{url: '/assets/js/inject_dartpad.js', defer: true}] The Dart language is designed to be easy to learn for coders coming from other languages, but it has a few unique features. -This codelab walks you through +This tutorial walks you through the most important of these language features. Dart 语言旨在让从其他编程语言转来的开发者们能够轻松学习,但也有它的独特之处。 @@ -18,12 +18,12 @@ Dart 语言旨在让从其他编程语言转来的开发者们能够轻松学习 [Dart 语言速查表](/guides/language/cheatsheet) 为你介绍一些最重要的语言特性。 -The embedded editors in this codelab have partially completed code snippets. +The embedded editors in this tutorial have partially completed code snippets. You can use these editors to test your knowledge by completing the code and clicking the **Run** button. The editors also contain thorough test code; **don't edit the test code**, but feel free to study it to learn about testing. -在这篇 codelab 中的嵌入式编辑器已经完成了部分代码片段。 +这篇教程中的嵌入式编辑器已经完成了部分代码片段。 你可以在这些编辑器上将代码补充完整,然后点击 **Run (运行)** 按钮进行测试。 这些编辑器上还包含了健全的测试代码; 你可以随时研究这些代码来学习测试方面的知识,但 **不要编辑测试代码**。 @@ -153,21 +153,22 @@ int? a; // The initial value of a is null. To learn more about null safety in Dart, read the [sound null safety guide](/null-safety). -想了解更多有关 Dart 的空安全的内容,请阅读 [健全的空安全](/null-safety)。 +想了解更多有关 Dart 的空安全的内容, +请阅读 [健全的空安全](/null-safety)。 ### Code example {:.no_toc} ### 代码样例 {:.no_toc} -Try to declare two variables below: +Declare two variables in this DartPad: -试着定义以下两种变量: +在此 DartPad 中声明以下两种变量: -- A nullable `String` named `name` with the value `'Jane'`. +* A nullable `String` named `name` with the value `'Jane'`. 一个可空的 `String`,名为 `name`,值为 `'Jane'`。 -- A nullable `String` named `address` with the value `null`. +* A nullable `String` named `address` with the value `null`. 一个可空的 `String`,名为 `address`,值为 `null`。 @@ -213,7 +214,6 @@ void main() { - ## Null-aware operators ## 避空运算符 @@ -1389,11 +1389,14 @@ void main() { ## 异常 -Dart code can throw and catch exceptions. In contrast to Java, all of Dart's exceptions are unchecked -exceptions. Methods don't declare which exceptions they might throw, and you aren't required to catch -any exceptions. +Dart code can throw and catch exceptions. +In contrast to Java, all of Dart's exceptions are unchecked. +Methods don't declare which exceptions they might throw and +you aren't required to catch any exceptions. -Dart 代码可以抛出和捕获异常。与 Java 相比,Dart 的所有异常都是 unchecked exception。方法不会声明它们可能抛出的异常,你也不需要捕获任何异常。 +Dart 代码可以抛出和捕获异常。 +与 Java 不同的是,Dart 的所有异常都是 unchecked exception。 +方法不会声明它们可能抛出的异常,你也不需要捕获任何异常。 Dart provides `Exception` and `Error` types, but you're allowed to throw any non-null object: @@ -1508,12 +1511,17 @@ abstract class Logger { } void tryFunction(VoidFunction untrustworthy, Logger logger) { - // Invoking this method might cause an exception. - // TODO: Catch and handle them using try-on-catch-finally. - untrustworthy(); + try { + untrustworthy(); + } on ExceptionWithMessage catch (e) { + logger.logException(e.runtimeType, e.message); + } on Exception catch (e) { + logger.logException(e.runtimeType); + } finally { + logger.doneLogging(); + } } - // Tests your solution (Don't edit!): class MyLogger extends Logger { Type? lastType; @@ -2048,32 +2056,35 @@ class Shape { ### Code example {:.no_toc} -### 代码样例 {:.no_toc} - -Fill in the factory constructor named `IntegerHolder.fromList`, -making it do the following: +Replace the line `TODO();` in the factory constructor +named `IntegerHolder.fromList` to return the following: -填写名为 `IntegerHolder.fromList` 的工厂构造方法,使其执行以下操作: +替换名为 `IntegerHolder.fromList` 工厂构造函数中的 `TODO();` 行, +使其执行以下操作: * If the list has **one** value, - create an `IntegerSingle` with that value. + create an `IntegerSingle` instance using that value. - 若列表只有**一个**值,那么就用它来创建一个 `IntegerSingle`。 + 如果列表只有**一个**值,那么就用它来创建一个 `IntegerSingle` 实例。 * If the list has **two** values, - create an `IntegerDouble` with the values in order. + create an `IntegerDouble` instance using the values in order. - 如果这个列表有两个值,那么按其顺序创建一个 `IntegerDouble`。 + 如果这个列表有**两个**值,那么按其顺序创建一个 `IntegerDouble` 实例。 * If the list has **three** values, - create an `IntegerTriple` with the values in order. + create an `IntegerTriple` instance using the values in order. - 如果这个列表有三个值,那么按其顺序创建一个 `IntegerTriple`。 + 如果这个列表有**三个**值,那么按其顺序创建一个 `IntegerTriple` 实例。 * Otherwise, throw an `Error`. 否则,抛出一个 `Error`。 +If you succeed, the console should display `Success!`. + +如果成功,控制台应显示 `Success!`。 + ```dartpad class IntegerHolder { IntegerHolder(); @@ -2086,107 +2097,99 @@ class IntegerHolder { class IntegerSingle extends IntegerHolder { final int a; - IntegerSingle(this.a); + + IntegerSingle(this.a); } class IntegerDouble extends IntegerHolder { final int a; final int b; - IntegerDouble(this.a, this.b); + + IntegerDouble(this.a, this.b); } class IntegerTriple extends IntegerHolder { final int a; final int b; final int c; - IntegerTriple(this.a, this.b, this.c); -} + IntegerTriple(this.a, this.b, this.c); +} -// Tests your solution (Don't edit!): +// Tests your solution (Don't edit from this point to end of file): void main() { final errs = []; - bool _throwed = false; - try { - IntegerHolder.fromList([]); - } on UnimplementedError { - print('Test failed. Did you implement the method?'); - return; - } on Error { - _throwed = true; - } catch (e) { - print('Called IntegerSingle.fromList([]) and got an exception of \n type ${e.runtimeType}.'); - return; + // Run 5 tests to see which values have valid integer holders + for (var tests = 0; tests < 5; tests++) { + if (!testNumberOfArgs(errs, tests)) return; } - - if (!_throwed) { - errs.add('Called IntegerSingle.fromList([]) and didn\'t throw Error.'); - } - try { - final obj = IntegerHolder.fromList([1]); - - if (obj is! IntegerSingle) { - errs.add('Called IntegerHolder.fromList([1]) and got an object of type \n ${obj.runtimeType} instead of IntegerSingle.'); - } else { - if (obj.a != 1) { - errs.add('Called IntegerHolder.fromList([1]) and got an IntegerSingle with \n an \'a\' value of ${obj.a} instead of the expected (1).'); - } - } - } catch (e) { - print('Called IntegerHolder.fromList([]) and got an exception of \n type ${e.runtimeType}.'); - return; + // The goal is no errors with values 1 to 3, + // but have errors with values 0 and 4. + // The testNumberOfArgs method adds to the errs array if + // the values 1 to 3 have an error and + // the values 0 and 4 don't have an error + if (errs.isEmpty) { + print('Success!'); + } else { + errs.forEach(print); } +} +bool testNumberOfArgs(List errs, int count) { + bool _threw = false; + final ex = List.generate(count, (index) => index + 1); + final callTxt = "IntegerHolder.fromList(${ex})"; try { - final obj = IntegerHolder.fromList([1, 2]); - - if (obj is! IntegerDouble) { - errs.add('Called IntegerHolder.fromList([1, 2]) and got an object of type \n ${obj.runtimeType} instead of IntegerDouble.'); - } else { - if (obj.a != 1) { - errs.add('Called IntegerHolder.fromList([1, 2]) and got an IntegerDouble \n with an \'a\' value of ${obj.a} instead of the expected (1).'); - } - - if (obj.b != 2) { - errs.add('Called IntegerHolder.fromList([1, 2]) and got an IntegerDouble \n with an \'b\' value of ${obj.b} instead of the expected (2).'); - } - } + final obj = IntegerHolder.fromList(ex); + final String vals = count == 1 ? "value" : "values"; + // Uncomment the next line if you want to see the results realtime + // print("Testing with ${count} ${vals} using ${obj.runtimeType}."); + testValues(errs, ex, obj, callTxt); + } on Error { + _threw = true; } catch (e) { - print('Called IntegerHolder.fromList([1, 2]) and got an exception \n of type ${e.runtimeType}.'); - return; + switch (count) { + case (< 1 && > 3): + if (!_threw) { + errs.add('Called ${callTxt} and it didn\'t throw an Error.'); + } + default: + errs.add('Called $callTxt and received an Error.'); + } } + return true; +} - try { - final obj = IntegerHolder.fromList([1, 2, 3]); - - if (obj is! IntegerTriple) { - errs.add('Called IntegerHolder.fromList([1, 2, 3]) and got an object of type \n ${obj.runtimeType} instead of IntegerTriple.'); +void testValues(List errs, List expectedValues, IntegerHolder obj, + String callText) { + for (var i = 0; i < expectedValues.length; i++) { + int found; + if (obj is IntegerSingle) { + found = obj.a; + } else if (obj is IntegerDouble) { + found = i == 0 ? obj.a : obj.b; + } else if (obj is IntegerTriple) { + found = i == 0 + ? obj.a + : i == 1 + ? obj.b + : obj.c; } else { - if (obj.a != 1) { - errs.add('Called IntegerHolder.fromList([1, 2, 3]) and got an IntegerTriple \n with an \'a\' value of ${obj.a} instead of the expected (1).'); - } - - if (obj.b != 2) { - errs.add('Called IntegerHolder.fromList([1, 2, 3]) and got an IntegerTriple \n with an \'a\' value of ${obj.b} instead of the expected (2).'); - } - - if (obj.c != 3) { - errs.add('Called IntegerHolder.fromList([1, 2, 3]) and got an IntegerTriple \n with an \'a\' value of ${obj.b} instead of the expected (2).'); - } + throw ArgumentError( + "This IntegerHolder type (${obj.runtimeType}) is unsupported."); } - } catch (e) { - print('Called IntegerHolder.fromList([1, 2, 3]) and got an exception \n of type ${e.runtimeType}.'); - return; - } - if (errs.isEmpty) { - print('Success!'); - } else { - errs.forEach(print); + if (found != expectedValues[i]) { + errs.add( + "Called $callText and got a ${obj.runtimeType} " + + "with a property at index $i value of $found " + + "instead of the expected (${expectedValues[i]})."); + } } } + ```
@@ -2196,17 +2199,18 @@ void main() { check the length of the list, then create and return an `IntegerSingle`, `IntegerDouble`, or `IntegerTriple` as appropriate. - ```dart - factory IntegerHolder.fromList(List list) { - if (list.length == 1) { + Replace `TODO();` with the following code block. + + ```dart + switch (list.length) { + case 1: return IntegerSingle(list[0]); - } else if (list.length == 2) { + case 2: return IntegerDouble(list[0], list[1]); - } else if (list.length == 3) { + case 3: return IntegerTriple(list[0], list[1], list[2]); - } else { - throw Error(); - } + default: + throw ArgumentError("List must between 1 and 3 items. This list was ${list.length} items."); } ``` @@ -2426,17 +2430,20 @@ void main() { ## What's next? -## 下一步是什么? +## 接下来呢? -We hope you enjoyed using this codelab to learn or test your knowledge of +We hope you enjoyed using this tutorial to learn or test your knowledge of some of the most interesting features of the Dart language. -Here are some suggestions for what to do now: -我们希望你能够喜欢这个 codelab 来学习或测试你对 Dart 语言中一些最有趣的功能的知识。下面是一些有关现在该做什么的建议: +我们希望你能够喜欢这个教程来学习或测试你对 Dart 语言中一些有趣特性的了解。 + +What you can try next includes: + +接下来你可以尝试: -* Try [other Dart codelabs](/codelabs). +* Try [other Dart tutorials](/tutorials). - 尝试阅读 [其他 Dart codelab](/codelabs)。 + 尝试其他 Dart 教程。 * Read the [Dart language tour](/language). diff --git a/src/content/resources/glossary.md b/src/content/resources/glossary.md index 952e212d2..ead48da00 100644 --- a/src/content/resources/glossary.md +++ b/src/content/resources/glossary.md @@ -279,3 +279,60 @@ If not, the pattern _refutes_, or denies, the match. Refutable patterns appear in [_matching contexts_][]. [_matching contexts_]: /language/patterns#matching + +## Subclass + +A _subclass_ is a class that inherits the implementation of another class by using the +[`extends`](/language/extend) keyword, or by [mixin application](#mixin-application). + +```dart +class A extends B {} // A is a subclass of B; B is the superclass of A. + +class B1 extends A with M {} // B1 has the superclass `A with M`, which has the superclass A. +``` + +A subclass relation also implies an associated [subtype](#subtype) relation. +For example, `class A` implicitly defines an associated type `A` +which instances of the class `A` inhabit. +So, `class A extends B` declares not just that the class +`A` is a subclass of `B`, but also establishes that the *type* `A` is a +*subtype* of the type `B`. + +Subclass relations are a subset of subtype relations. +When the documentation says "`S` must be a subtype of `T`", +it's fine for `S` to be a subclass of `T`. +However, the converse is not true: not all subtypes are subclasses. +See the [subtype](#subtype) entry for more information. + +## Subtype + +A _subtype_ relation is where a value of a certain type is substitutable +where the value of another type, the supertype, is expected. +For example, if `S` is a subtype of `T`, +then you can substitute a value of type `S` +where a value of type `T` is expected. + +A subtype supports all of the operations of its supertype +(and possibly some extra operations). +In practice, this means you can assign the value of a subtype +to any location expecting the supertype, +and all of the methods of the supertype are available on the subtype. + +This is true at least statically. +A specific API might not allow the substitution at run time, +depending on its operations. + +Some subtype relations are based on the structure of the type, +like with nullable types (for example, `int` is a subtype of `int?`) +and function types +(for example, `String Function()` is a subtype of `void Function()`). + +Subtypes can also be introduced for classes by +[implementation](/language/classes#implicit-interfaces) +or [inheritance](/language/extend) (direct or indirect): + +```dart +class A implements B {} // A is a subtype of B, but NOT a subclass of B. + +class C extends D {} // C is a subtype AND a subclass of D. +``` diff --git a/src/content/tools/dartpad/index.md b/src/content/tools/dartpad/index.md index ccdb9f84e..6d809cc20 100644 --- a/src/content/tools/dartpad/index.md +++ b/src/content/tools/dartpad/index.md @@ -7,14 +7,14 @@ description: 在浏览器里体验 Dart 编程语言的工具。 DartPad is an [open source tool]({{site.repo.dart.org}}/dart-pad) that lets you play with the Dart language in any modern browser. -Many pages in this site—especially [codelabs](/codelabs)—have +Many pages in this site—especially [tutorials](/tutorials), have [embedded DartPads](#embedding). To open DartPad as a standalone web page, visit the [DartPad site (dartpad.dev)][DartPad]{:target="_blank" rel="noopener"}. DartPad 是一个可以让你在任何现代化的浏览器中体验 Dart 编程语言线上工具, -它是 [开源](https://github.com/dart-lang/dart-pad) 的。 -本网页里一些页面,尤其是 [codelabs](/codelabs) 页面, +它是 [开源]({{site.repo.dart.org}}/dart-pad) 的。 +本网页里一些页面,尤其是 [Dart 语言教程文档](/tutorials) 页面, 包含了很多[内嵌的 DartPads](#embedding)。 你可以在浏览器里输入下面的网址打开一个 DartPad 页面。 )>()!] -[!void free(Pointer ptr) {}!] +@Native)>() +void [!free!](Pointer ptr) {} ``` #### Common fixes @@ -7182,8 +7182,8 @@ has one argument and the type of the annotated function ```dart import 'dart:ffi'; -[!@Native(symbol: 'f')!] -[!external void f(double x, double y);!] +@Native(symbol: 'f') +external void [!f!](double x, double y); ``` #### Common fixes @@ -7229,8 +7229,8 @@ for the receiver of the method: import 'dart:ffi'; class C { - [!@Native()!] - [!external void f(double x);!] + @Native() + external void [!f!](double x); } ``` @@ -12219,7 +12219,7 @@ returns a `Handle`, but the `isLeaf` argument is `true`: import 'dart:ffi'; void f(Pointer> p) { - [!p.asFunction(isLeaf: true)!]; + p.[!asFunction!](isLeaf: true); } ``` @@ -12268,7 +12268,7 @@ parameter of type `Handle`, but the `isLeaf` argument is `true`: import 'dart:ffi'; void f(Pointer> p) { - [!p.asFunction(isLeaf: true)!]; + p.[!asFunction!](isLeaf: true); } ``` @@ -15636,52 +15636,6 @@ class A { class B implements A {} ``` -### non_leaf_call_must_not_take_typed_data - -_FFI non-leaf calls can't take typed data arguments._ - -#### Description - -The analyzer produces this diagnostic when the value of the `isLeaf` -argument of `Pointer.asFunction`, `DynamicLibrary.lookupFunction`, or -`@Native` is `false` and the Dart function signature contains a typed -data parameter. - -Typed data unwrapping is only supported on arguments for leaf FFI calls. - -For more information about FFI, see [C interop using dart:ffi][ffi]. - -#### Example - -The following code produces this diagnostic because the dart function -signature contains a typed data, but the `isLeaf` argument is `false`: - -```dart -import 'dart:ffi'; -import 'dart:typed_data'; - -void f(Pointer)>> p) { - p.asFunction<[!void Function(Uint8List)!]>(); -} -``` - -#### Common fixes - -If the function has at least one typed data parameter, then add -the `isLeaf` argument: - -```dart -import 'dart:ffi'; -import 'dart:typed_data'; - -void f(Pointer)>> p) { - p.asFunction(isLeaf: true); -} -``` - -If the function also uses `Handle`s, then it must be non-leaf. In That -case use `Pointer`s instead of typed data. - ### non_native_function_type_argument_to_pointer _Can't invoke 'asFunction' because the function signature '{0}' for the pointer @@ -19073,7 +19027,8 @@ int f() => 3; ### return_of_invalid_type_from_closure -_The return type '{0}' isn't a '{1}', as required by the closure's context._ +_The returned type '{0}' isn't returnable from a '{1}' function, as required by +the closure's context._ #### Description @@ -23520,7 +23475,7 @@ _Target of URI doesn't exist: '{0}'._ The analyzer produces this diagnostic when an import, export, or part directive is found where the URI refers to a file that doesn't exist. -#### Example +#### Examples If the file `lib.dart` doesn't exist, the following code produces this diagnostic: @@ -23529,6 +23484,14 @@ diagnostic: import [!'lib.dart'!]; ``` +If the file `lib.dart` doesn't exist, the following code produces this +diagnostic: + +```dart +/// @docImport [!'lib.dart'!]; +library; +``` + #### Common fixes If the URI was mistyped or invalid, then correct the URI. @@ -23761,6 +23724,100 @@ const int x = 0; const int y = x; ``` +### workspace_field_not_list + +_The value of the 'workspace' field is required to be a list of relative file +paths._ + +#### Description + +The analyzer produces this diagnostic when the value of the `workspace` key +isn't a list. + +#### Example + +The following code produces this diagnostic because the value of the +`workspace` key is a string when a list is expected: + +```yaml +name: example +workspace: [!notPaths!] +``` + +#### Common fixes + +Change the value of the workspace field so that it's a list: + +```yaml +name: example +workspace: + - pkg/package_1 + - pkg/package_2 +``` + +### workspace_value_not_string + +_Workspace entries are required to be directory paths (strings)._ + +#### Description + +The analyzer produces this diagnostic when a `workspace` list contains a +value that isn't a string. + +#### Example + +The following code produces this diagnostic because the `workspace` list +contains a map: + +```yaml +name: example +workspace: + - [!image.gif: true!] +``` + +#### Common fixes + +Change the `workspace` list so that it only contains valid POSIX-style directory +paths: + +```yaml +name: example +workspace: + - pkg/package_1 + - pkg/package_2 +``` + +### workspace_value_not_subdirectory + +_Workspace values must be a relative path of a subdirectory of '{0}'._ + +#### Description + +The analyzer produces this diagnostic when a `workspace` list contains a +value that is not a subdirectory of the directory containing the `pubspec.yaml`` file. + +#### Example + +The following code produces this diagnostic because the value in the `workspace` list is not a +relative path of a subdirectory of the directory containing the 'pubspec.yaml' file: + +```yaml +name: example +workspace: + - /home/my_package +``` + +#### Common fixes + +Change the `workspace` list so that it only contains only subdirectory paths. + +```yaml +name: example +workspace: + - pkg/package_1 + - pkg/package_2 +``` + ### wrong_number_of_parameters_for_operator _Operator '-' should declare 0 or 1 parameter, but {0} found._ @@ -24154,55 +24211,4515 @@ Iterable get zero sync* { } ``` -### invalid_use_of_do_not_submit_member +### always_declare_return_types -_Uses of '{0}' should not be submitted to source control._ +_The function '{0}' should have a return type but doesn't._ + +_The method '{0}' should have a return type but doesn't._ #### Description -The analyzer produces this diagnostic when a member that is annotated with -[`@doNotSubmit`][meta-doNotSubmit] is referenced outside of a member -declaration that is also annotated with `@doNotSubmit`. +The analyzer produces this diagnostic when a method or function doesn't +have an explicit return type. #### Example -Given a file `a.dart` containing the following declaration: +The following code produces this diagnostic because the function `f` +doesn't have a return type: ```dart -import 'package:meta/meta.dart'; +[!f!]() {} +``` -@doNotSubmit -void emulateCrash() { /* ... */ } +#### Common fixes + +Add an explicit return type: + +```dart +void f() {} ``` -The following code produces this diagnostic because the declaration is -being referenced outside of a member that is also annotated with -`@doNotSubmit`: +### always_put_control_body_on_new_line + +_Statement should be on a separate line._ + +#### Description + +The analyzer produces this diagnostic when the code being controlled by a +control flow statement (`if`, `for`, `while`, or `do`) is on the same line +as the control flow statement. + +#### Example + +The following code produces this diagnostic because the `return` statement +is on the same line as the `if` that controls whether the `return` will be +executed: ```dart -import 'a.dart'; +void f(bool b) { + if (b) [!return!]; +} +``` -void f() { - [!emulateCrash!](); +#### Common fixes + +Put the controlled statement onto a separate, indented, line: + +```dart +void f(bool b) { + if (b) + return; } ``` +### always_put_required_named_parameters_first + +_Required named parameters should be before optional named parameters._ + +#### Description + +The analyzer produces this diagnostic when required named parameters occur +after optional named parameters. + +#### Example + +The following code produces this diagnostic because the required parameter +`x` is after the optional parameter `y`: + +```dart +void f({int? y, required int [!x!]}) {} +``` + #### Common fixes -Most commonly, when complete with local testing, the reference to the -member should be removed. +Reorder the parameters so that all required named parameters are before +any optional named parameters: -If building additional functionality on top of the member, annotate the -newly added member with `@doNotSubmit` as well: +```dart +void f({required int x, int? y}) {} +``` + +### always_use_package_imports + +_Use 'package:' imports for files in the 'lib' directory._ + +#### Description + +The analyzer produces this diagnostic when an `import` in a library inside +the `lib` directory uses a relative path to import another library inside +the `lib` directory of the same package. + +#### Example + +Given that a file named `a.dart` and the code below are both inside the +`lib` directory of the same package, the following code produces this +diagnostic because a relative URI is used to import `a.dart`: ```dart -import 'package:meta/meta.dart'; +import [!'a.dart'!]; +``` -import 'a.dart'; +#### Common fixes -@doNotSubmit -void emulateCrashWithOtherFunctionality() { - emulateCrash(); - // do other things. +Use a package import: + +```dart +import 'package:p/a.dart'; +``` + +### annotate_overrides + +_The member '{0}' overrides an inherited member but isn't annotated with +'@override'._ + +#### Description + +The analyzer produces this diagnostic when a member overrides an inherited +member, but isn't annotated with `@override`. + +#### Example + +The following code produces this diagnostic because the method `m` in the +class `B` overrides the method with the same name in class `A`, but isn't +marked as an intentional override: + +```dart +class A { + void m() {} +} + +class B extends A { + void [!m!]() {} +} +``` + +#### Common fixes + +If the member in the subclass is intended to override the member in the +superclass, then add an `@override` annotation: + +```dart +class A { + void m() {} +} + +class B extends A { + @override + void m() {} +} +``` + +If the member in the subclass is not intended to override the member in +the superclass, then rename one of the members: + +```dart +class A { + void m() {} +} + +class B extends A { + void m2() {} +} +``` + +### avoid_empty_else + +_Empty statements are not allowed in an 'else' clause._ + +#### Description + +The analyzer produces this diagnostic when the statement after an `else` +is an empty statement (a semicolon). + +For more information, see the documentation for +[`avoid_empty_else`](https://dart.dev/diagnostics/avoid_empty_else). + +#### Example + +The following code produces this diagnostic because the statement +following the `else` is an empty statement: + +```dart +void f(int x, int y) { + if (x > y) + print("1"); + else [!;!] + print("2"); +} +``` + +#### Common fixes + +If the statement after the empty statement is intended to be executed only +when the condition is `false`, then remove the empty statement: + +```dart +void f(int x, int y) { + if (x > y) + print("1"); + else + print("2"); +} +``` + +If there is no code that is intended to be executed only when the +condition is `false`, then remove the whole `else` clause: + +```dart +void f(int x, int y) { + if (x > y) + print("1"); + print("2"); } ``` + +### avoid_function_literals_in_foreach_calls + +_Function literals shouldn't be passed to 'forEach'._ + +#### Description + +The analyzer produces this diagnostic when the argument to +`Iterable.forEach` is a closure. + +#### Example + +The following code produces this diagnostic because the argument to the +invocation of `forEach` is a closure: + +```dart +void f(Iterable s) { + s.[!forEach!]((e) => print(e)); +} +``` + +#### Common fixes + +If the closure can be replaced by a tear-off, then replace the closure: + +```dart +void f(Iterable s) { + s.forEach(print); +} +``` + +If the closure can't be replaced by a tear-off, then use a `for` loop to +iterate over the elements: + +```dart +void f(Iterable s) { + for (var e in s) { + print(e); + } +} +``` + +### avoid_init_to_null + +_Redundant initialization to 'null'._ + +#### Description + +The analyzer produces this diagnostic when a nullable variable is +explicitly initialized to `null`. The variable can be a local variable, +field, or top-level variable. + +A variable or field that isn't explicitly initialized automatically gets +initialized to `null`. There's no concept of "uninitialized memory" in +Dart. + +#### Example + +The following code produces this diagnostic because the variable `f` is +explicitly initialized to `null`: + +```dart +class C { + int? [!f = null!]; + + void m() { + if (f != null) { + print(f); + } + } +} +``` + +#### Common fixes + +Remove the unnecessary initialization: + +```dart +class C { + int? f; + + void m() { + if (f != null) { + print(f); + } + } +} +``` + +### avoid_print + +_Don't invoke 'print' in production code._ + +#### Description + +The analyzer produces this diagnostic when the function `print` is invoked +in production code. + +#### Example + +The following code produces this diagnostic because the function `print` +can't be invoked in production: + +```dart +void f(int x) { + [!print!]('x = $x'); +} +``` + +#### Common fixes + +If you're writing code that uses Flutter, then use the function +[`debugPrint`][debugPrint], guarded by a test +using [`kDebugMode`][kDebugMode]: + +```dart +import 'package:flutter/foundation.dart'; + +void f(int x) { + if (kDebugMode) { + debugPrint('x = $x'); + } +} +``` + +If you're writing code that doesn't use Flutter, then use a logging +service, such as [`package:logging`][package-logging], to write the +information. + +### avoid_relative_lib_imports + +_Can't use a relative path to import a library in 'lib'._ + +#### Description + +The analyzer produces this diagnostic when the URI in an `import` +directive has `lib` in the path. + +#### Example + +Assuming that there is a file named `a.dart` in the `lib` directory: + +```dart +class A {} +``` + +The following code produces this diagnostic because the import contains a +path that includes `lib`: + +```dart +import [!'../lib/a.dart'!]; +``` + +#### Common fixes + +Rewrite the import to not include `lib` in the URI: + +```dart +import 'a.dart'; +``` + +### avoid_renaming_method_parameters + +_The parameter name '{0}' doesn't match the name '{1}' in the overridden +method._ + +#### Description + +The analyzer produces this diagnostic when a method that overrides a +method from a superclass changes the names of the parameters. + +#### Example + +The following code produces this diagnostic because the parameter of the +method `m` in `B` is named `b`, which is different from the name of the +overridden method's parameter in `A`: + +```dart +class A { + void m(int a) {} +} + +class B extends A { + @override + void m(int [!b!]) {} +} +``` + +#### Common fixes + +Rename one of the parameters so that they are the same: + +```dart +class A { + void m(int a) {} +} + +class B extends A { + @override + void m(int a) {} +} +``` + +### avoid_return_types_on_setters + +_Unnecessary return type on a setter._ + +#### Description + +The analyzer produces this diagnostic when a setter has an explicit return +type. + +Setters never return a value, so declaring the return type of one is +redundant. + +#### Example + +The following code produces this diagnostic because the setter `s` has an +explicit return type (`void`): + +```dart +[!void!] set s(int p) {} +``` + +#### Common fixes + +Remove the return type: + +```dart +set s(int p) {} +``` + +### avoid_returning_null_for_void + +_Don't return 'null' from a function with a return type of 'void'._ + +_Don't return 'null' from a method with a return type of 'void'._ + +#### Description + +The analyzer produces this diagnostic when a function that has a return +type of `void` explicitly returns `null`. + +#### Example + +The following code produces this diagnostic because there is an explicit +return of `null` in a `void` function: + +```dart +void f() { + [!return null;!] +} +``` + +#### Common fixes + +Remove the unnecessary explicit `null`: + +```dart +void f() { + return; +} +``` + +### avoid_shadowing_type_parameters + +_The type parameter '{0}' shadows a type parameter from the enclosing {1}._ + +#### Description + +The analyzer produces this diagnostic when a type parameter shadows a type +parameter from an enclosing declaration. + +Shadowing a type parameter with a different type parameter can lead to +subtle bugs that are difficult to debug. + +#### Example + +The following code produces this diagnostic because the type parameter `T` +defined by the method `m` shadows the type parameter `T` defined by the +class `C`: + +```dart +class C { + void m<[!T!]>() {} +} +``` + +#### Common fixes + +Rename one of the type parameters: + +```dart +class C { + void m() {} +} +``` + +### avoid_single_cascade_in_expression_statements + +_Unnecessary cascade expression._ + +#### Description + +The analyzer produces this diagnostic when a single cascade operator is +used and the value of the expression isn't being used for anything (such +as being assigned to a variable or being passed as an argument). + +#### Example + +The following code produces this diagnostic because the value of the +cascade expression `s..length` isn't being used: + +```dart +void f(String s) { + [!s..length!]; +} +``` + +#### Common fixes + +Replace the cascade operator with a simple access operator: + +```dart +void f(String s) { + s.length; +} +``` + +### avoid_slow_async_io + +_Use of an async 'dart:io' method._ + +#### Description + +The analyzer produces this diagnostic when an asynchronous file I/O method +with a synchronous equivalent is used. + +The following are the specific flagged asynchronous methods: + +- `Directory.exists` +- `Directory.stat` +- `File.lastModified` +- `File.exists` +- `File.stat` +- `FileSystemEntity.isDirectory` +- `FileSystemEntity.isFile` +- `FileSystemEntity.isLink` +- `FileSystemEntity.type` + +#### Example + +The following code produces this diagnostic because the async method +`exists` is invoked: + +```dart +import 'dart:io'; + +Future g(File f) async { + await [!f.exists()!]; +} +``` + +#### Common fixes + +Use the synchronous version of the method: + +```dart +import 'dart:io'; + +void g(File f) { + f.existsSync(); +} +``` + +### avoid_type_to_string + +_Using 'toString' on a 'Type' is not safe in production code._ + +#### Description + +The analyzer produces this diagnostic when the method `toString` is +invoked on a value whose static type is `Type`. + +#### Example + +The following code produces this diagnostic because the method `toString` +is invoked on the `Type` returned by `runtimeType`: + +```dart +bool isC(Object o) => o.runtimeType.[!toString!]() == 'C'; + +class C {} +``` + +#### Common fixes + +If it's essential that the type is exactly the same, then use an explicit +comparison: + +```dart +bool isC(Object o) => o.runtimeType == C; + +class C {} +``` + +If it's alright for instances of subtypes of the type to return `true`, +then use a type check: + +```dart +bool isC(Object o) => o is C; + +class C {} +``` + +### avoid_types_as_parameter_names + +_The parameter name '{0}' matches a visible type name._ + +#### Description + +The analyzer produces this diagnostic when the name of a parameter in a +parameter list is the same as a visible type (a type whose name is in +scope). + +This often indicates that the intended name of the parameter is missing, +causing the name of the type to be used as the name of the parameter +rather than the type of the parameter. Even when that's not the case (the +name of the parameter is intentional), the name of the parameter will +shadow the existing type, which can lead to bugs that are difficult to +diagnose. + +#### Example + +The following code produces this diagnostic because the function `f` has a +parameter named `int`, which shadows the type `int` from `dart:core`: + +```dart +void f([!int!]) {} +``` + +#### Common fixes + +If the parameter name is missing, then add a name for the parameter: + +```dart +void f(int x) {} +``` + +If the parameter is intended to have an implicit type of `dynamic`, then +rename the parameter so that it doesn't shadow the name of any visible type: + +```dart +void f(int_) {} +``` + +### avoid_unnecessary_containers + +_Unnecessary instance of 'Container'._ + +#### Description + +The analyzer produces this diagnostic when a widget tree contains an +instance of `Container` and the only argument to the constructor is +`child:`. + +#### Example + +The following code produces this diagnostic because the invocation of the +`Container` constructor only has a `child:` argument: + +```dart +import 'package:flutter/material.dart'; + +Widget buildRow() { + return [!Container!]( + child: Row( + children: [ + Text('a'), + Text('b'), + ], + ) + ); +} +``` + +#### Common fixes + +If you intended to provide other arguments to the constructor, then add +them: + +```dart +import 'package:flutter/material.dart'; + +Widget buildRow() { + return Container( + color: Colors.red.shade100, + child: Row( + children: [ + Text('a'), + Text('b'), + ], + ) + ); +} +``` + +If no other arguments are needed, then unwrap the child widget: + +```dart +import 'package:flutter/material.dart'; + +Widget buildRow() { + return Row( + children: [ + Text('a'), + Text('b'), + ], + ); +} +``` + +### avoid_web_libraries_in_flutter + +_Don't use web-only libraries outside Flutter web plugin packages._ + +#### Description + +The analyzer produces this diagnostic when a library in a package that +isn't a web plugin contains an import of a web-only library: +- `dart:html` +- `dart:js` +- `dart:js_util` +- `dart:js_interop` +- `dart:js_interop_unsafe` +- `package:js` +- `package:web` + +#### Example + +When found in a package that isn't a web plugin, the following code +produces this diagnostic because it imports `dart:html`: + +```dart +import [!'dart:html'!]; + +import 'package:flutter/material.dart'; + +class C {} +``` + +#### Common fixes + +If the package isn't intended to be a web plugin, then remove the import: + +```dart +import 'package:flutter/material.dart'; + +class C {} +``` + +If the package is intended to be a web plugin, then add the following +lines to the `pubspec.yaml` file of the package: + +```yaml +flutter: + plugin: + platforms: + web: + pluginClass: HelloPlugin + fileName: hello_web.dart +``` + +See [Developing packages & plugins](https://flutter.dev/to/develop-packages) +for more information. + +### await_only_futures + +_Uses 'await' on an instance of '{0}', which is not a subtype of 'Future'._ + +#### Description + +The analyzer produces this diagnostic when the expression after `await` +has any type other than `Future`, `FutureOr`, `Future?`, +`FutureOr?` or `dynamic`. + +An exception is made for the expression `await null` because it is a +common way to introduce a microtask delay. + +Unless the expression can produce a `Future`, the `await` is unnecessary +and can cause a reader to assume a level of asynchrony that doesn't exist. + +#### Example + +The following code produces this diagnostic because the expression after +`await` has the type `int`: + +```dart +void f() async { + [!await!] 23; +} +``` + +#### Common fixes + +Remove the `await`: + +```dart +void f() async { + 23; +} +``` + +### camel_case_extensions + +_The extension name '{0}' isn't an UpperCamelCase identifier._ + +#### Description + +The analyzer produces this diagnostic when the name of an extension +doesn't use the 'UpperCamelCase' naming convention. + +#### Example + +The following code produces this diagnostic because the name of the +extension doesn't start with an uppercase letter: + +```dart +extension [!stringExtension!] on String {} +``` + +#### Common fixes + +If the extension needs to have a name (needs to be visible outside this +library), then rename the extension so that it has a valid name: + +```dart +extension StringExtension on String {} +``` + +If the extension doesn't need to have a name, then remove the name of the +extension: + +```dart +extension on String {} +``` + +### camel_case_types + +_The type name '{0}' isn't an UpperCamelCase identifier._ + +#### Description + +The analyzer produces this diagnostic when the name of a type (a class, +mixin, enum, or typedef) doesn't use the 'UpperCamelCase' naming +convention. + +#### Example + +The following code produces this diagnostic because the name of the class +doesn't start with an uppercase letter: + +```dart +class [!c!] {} +``` + +#### Common fixes + +Rename the type so that it has a valid name: + +```dart +class C {} +``` + +### cancel_subscriptions + +_Uncancelled instance of 'StreamSubscription'._ + +#### Description + +The analyzer produces this diagnostic when an instance of +`StreamSubscription` is created but the method `cancel` isn't invoked. + +#### Example + +The following code produces this diagnostic because the `subscription` +isn't canceled: + +```dart +import 'dart:async'; + +void f(Stream stream) { + // ignore: unused_local_variable + var [!subscription = stream.listen((_) {})!]; +} +``` + +#### Common fixes + +Cancel the subscription: + +```dart +import 'dart:async'; + +void f(Stream stream) { + var subscription = stream.listen((_) {}); + subscription.cancel(); +} +``` + +### close_sinks + +_Unclosed instance of 'Sink'._ + +#### Description + +The analyzer produces this diagnostic when an instance of `Sink` is +created but the method `close` isn't invoked. + +#### Example + +The following code produces this diagnostic because the `sink` isn't +closed: + +```dart +import 'dart:io'; + +void g(File f) { + var [!sink = f.openWrite()!]; + sink.write('x'); +} +``` + +#### Common fixes + +Close the sink: + +```dart +import 'dart:io'; + +void g(File f) { + var sink = f.openWrite(); + sink.write('x'); + sink.close(); +} +``` + +### collection_methods_unrelated_type + +_The argument type '{0}' isn't related to '{1}'._ + +#### Description + +The analyzer produces this diagnostic when any one of several methods in +the core libraries are invoked with arguments of an inappropriate type. +These methods are ones that don't provide a specific enough type for the +parameter to allow the normal type checking to catch the error. + +The arguments that are checked are: +- an argument to `Iterable.contains` should be related to `E` +- an argument to `List.remove` should be related to `E` +- an argument to `Map.containsKey` should be related to `K` +- an argument to `Map.containsValue` should be related to `V` +- an argument to `Map.remove` should be related to `K` +- an argument to `Map.[]` should be related to `K` +- an argument to `Queue.remove` should be related to `E` +- an argument to `Set.lookup` should be related to `E` +- an argument to `Set.remove` should be related to `E` + +#### Example + +The following code produces this diagnostic because the argument to +`contains` is a `String`, which isn't assignable to `int`, the element +type of the list `l`: + +```dart +bool f(List l) => l.contains([!'1'!]); +``` + +#### Common fixes + +If the element type is correct, then change the argument to have the same +type: + +```dart +bool f(List l) => l.contains(1); +``` + +If the argument type is correct, then change the element type: + +```dart +bool f(List l) => l.contains('1'); +``` + +### constant_identifier_names + +_The constant name '{0}' isn't a lowerCamelCase identifier._ + +#### Description + +The analyzer produces this diagnostic when the name of a constant doesn't +follow the lowerCamelCase naming convention. + +#### Example + +The following code produces this diagnostic because the name of the +top-level variable isn't a lowerCamelCase identifier: + +```dart +const [!EMPTY_STRING!] = ''; +``` + +#### Common fixes + +Rewrite the name to follow the lowerCamelCase naming convention: + +```dart +const emptyString = ''; +``` + +### control_flow_in_finally + +_Use of '{0}' in a 'finally' clause._ + +#### Description + +The analyzer produces this diagnostic when a `finally` clause contains a +`return`, `break`, or `continue` statement. + +#### Example + +The following code produces this diagnostic because there is a `return` +statement inside a `finally` block: + +```dart +int f() { + try { + return 1; + } catch (e) { + print(e); + } finally { + [!return 0;!] + } +} +``` + +#### Common fixes + +If the statement isn't needed, then remove the statement, and remove the +`finally` clause if the block is empty: + +```dart +int f() { + try { + return 1; + } catch (e) { + print(e); + } +} +``` + +If the statement is needed, then move the statement outside the `finally` +block: + +```dart +int f() { + try { + return 1; + } catch (e) { + print(e); + } + return 0; +} +``` + +### curly_braces_in_flow_control_structures + +_Statements in {0} should be enclosed in a block._ + +#### Description + +The analyzer produces this diagnostic when a control structure (`if`, +`for`, `while`, or `do` statement) has a statement other than a block. + +#### Example + +The following code produces this diagnostic because the `then` statement +is not enclosed in a block: + +```dart +int f(bool b) { + if (b) + [!return 1;!] + return 0; +} +``` + +#### Common fixes + +Add braces around the statement that should be a block: + +```dart +int f(bool b) { + if (b) { + return 1; + } + return 0; +} +``` + +### dangling_library_doc_comments + +_Dangling library doc comment._ + +#### Description + +The analyzer produces this diagnostic when a documentation comment that +appears to be library documentation isn't followed by a `library` +directive. More specifically, it is produced when a documentation comment +appears before the first directive in the library, assuming that it isn't +a `library` directive, or before the first top-level declaration and is +separated from the declaration by one or more blank lines. + +#### Example + +The following code produces this diagnostic because there's a +documentation comment before the first `import` directive: + +```dart +[!/// This is a great library.!] +import 'dart:core'; +``` + +The following code produces this diagnostic because there's a +documentation comment before the first class declaration, but there's a +blank line between the comment and the declaration. + +```dart +[!/// This is a great library.!] + +class C {} +``` + +#### Common fixes + +If the comment is library documentation, then add a `library` directive +without a name: + +```dart +/// This is a great library. +library; + +import 'dart:core'; +``` + +If the comment is documentation for the following declaration, then remove +the blank line: + +```dart +/// This is a great library. +class C {} +``` + +### depend_on_referenced_packages + +_The imported package '{0}' isn't a dependency of the importing package._ + +#### Description + +The analyzer produces this diagnostic when a package import refers to a +package that is not specified in the `pubspec.yaml` file. + +Depending explicitly on packages that you reference ensures they will +always exist and allows you to put a dependency constraint on them to +guard against breaking changes. + +#### Example + +Given a `pubspec.yaml` file containing the following: + +```yaml +dependencies: + meta: ^3.0.0 +``` + +The following code produces this diagnostic because there is no dependency +on the package `a`: + +```dart +import 'package:a/a.dart'; +``` + +#### Common fixes + +Whether the dependency should be a regular dependency or dev dependency +depends on whether the package is referenced from a public library (one +under either `lib` or `bin`), or only private libraries, (such as one +under `test`). + +If the package is referenced from at least one public library, then add a +regular dependency on the package to the `pubspec.yaml` file under the +`dependencies` field: + +```yaml +dependencies: + a: ^1.0.0 + meta: ^3.0.0 +``` + +If the package is referenced only from private libraries, then add a +dev dependency on the package to the `pubspec.yaml` file under the +`dev_dependencies` field: + +```yaml +dependencies: + meta: ^3.0.0 +dev_dependencies: + a: ^1.0.0 +``` + +### empty_catches + +_Empty catch block._ + +#### Description + +The analyzer produces this diagnostic when the block in a `catch` clause +is empty. + +#### Example + +The following code produces this diagnostic because the catch block is +empty: + +```dart +void f() { + try { + print('Hello'); + } catch (exception) [!{}!] +} +``` + +#### Common fixes + +If the exception shouldn't be ignored, then add code to handle the +exception: + +```dart +void f() { + try { + print('We can print.'); + } catch (exception) { + print("We can't print."); + } +} +``` + +If the exception is intended to be ignored, then add a comment explaining +why: + +```dart +void f() { + try { + print('We can print.'); + } catch (exception) { + // Nothing to do. + } +} +``` + +If the exception is intended to be ignored and there isn't any good +explanation for why, then rename the exception parameter: + +```dart +void f() { + try { + print('We can print.'); + } catch (_) {} +} +``` + +### empty_constructor_bodies + +_Empty constructor bodies should be written using a ';' rather than '{}'._ + +#### Description + +The analyzer produces this diagnostic when a constructor has an empty +block body. + +#### Example + +The following code produces this diagnostic because the constructor for +`C` has a block body that is empty: + +```dart +class C { + C() [!{}!] +} +``` + +#### Common fixes + +Replace the block with a semicolon: + +```dart +class C { + C(); +} +``` + +### empty_statements + +_Unnecessary empty statement._ + +#### Description + +The analyzer produces this diagnostic when an empty statement is found. + +#### Example + +The following code produces this diagnostic because the statement +controlled by the `while` loop is an empty statement: + +```dart +void f(bool condition) { + while (condition)[!;!] + g(); +} + +void g() {} +``` + +#### Common fixes + +If there are no statements that need to be controlled, then remove both +the empty statement and the control structure it's part of (being careful +that any other code being removed doesn't have a side-effect that needs to +be preserved): + +```dart +void f(bool condition) { + g(); +} + +void g() {} +``` + +If there are no statements that need to be controlled but the control +structure is still required for other reasons, then replace the empty +statement with a block to make the structure of the code more obvious: + +```dart +void f(bool condition) { + while (condition) {} + g(); +} + +void g() {} +``` + +If there are statements that need to be controlled, remove the empty +statement and adjust the code so that the appropriate statements are being +controlled, possibly adding a block: + +```dart +void f(bool condition) { + while (condition) { + g(); + } +} + +void g() {} +``` + +### file_names + +_The file name '{0}' isn't a lower\_case\_with\_underscores identifier._ + +#### Description + +The analyzer produces this diagnostic when the name of a `.dart` file +doesn't use lower_case_with_underscores. + +#### Example + +A file named `SliderMenu.dart` produces this diagnostic because the file +name uses the UpperCamelCase convention. + +#### Common fixes + +Rename the file to use the lower_case_with_underscores convention, such as +`slider_menu.dart`. + +### hash_and_equals + +_Missing a corresponding override of '{0}'._ + +#### Description + +The analyzer produces this diagnostic when a class or mixin either +overrides the definition of `==` but doesn't override the definition of +`hashCode`, or conversely overrides the definition of `hashCode` but +doesn't override the definition of `==`. + +Both the `==` operator and the `hashCode` property of objects must be +consistent for a common hash map implementation to function properly. As a +result, when overriding either method, both should be overridden. + +#### Example + +The following code produces this diagnostic because the class `C` +overrides the `==` operator but doesn't override the getter `hashCode`: + +```dart +class C { + final int value; + + C(this.value); + + @override + bool operator [!==!](Object other) => + other is C && + other.runtimeType == runtimeType && + other.value == value; +} +``` + +#### Common fixes + +If you need to override one of the members, then add an override of the +other: + +```dart +class C { + final int value; + + C(this.value); + + @override + bool operator ==(Object other) => + other is C && + other.runtimeType == runtimeType && + other.value == value; + + @override + int get hashCode => value.hashCode; +} +``` + +If you don't need to override either of the members, then remove the +unnecessary override: + +```dart +class C { + final int value; + + C(this.value); +} +``` + +### implementation_imports + +_Import of a library in the 'lib/src' directory of another package._ + +#### Description + +The analyzer produces this diagnostic when an import references a library +that's inside the `lib/src` directory of a different package, which +violates [the convention for pub +packages](https://dart.dev/tools/pub/package-layout#implementation-files). + +#### Example + +The following code, assuming that it isn't part of the `ffi` package, +produces this diagnostic because the library being imported is inside the +top-level `src` directory: + +```dart +import [!'package:ffi/src/allocation.dart'!]; +``` + +#### Common fixes + +If the library being imported contains code that's part of the public API, +then import the public library that exports the public API: + +```dart +import 'package:ffi/ffi.dart'; +``` + +If the library being imported isn't part of the public API of the package, +then either find a different way to accomplish your goal, assuming that +it's possible, or open an issue asking the package authors to make it part +of the public API. + +### implicit_call_tearoffs + +_Implicit tear-off of the 'call' method._ + +#### Description + +The analyzer produces this diagnostic when an object with a `call` method +is assigned to a function-typed variable, implicitly tearing off the +`call` method. + +#### Example + +The following code produces this diagnostic because an instance of +`Callable` is passed to a function expecting a `Function`: + +```dart +class Callable { + void call() {} +} + +void callIt(void Function() f) { + f(); +} + +void f() { + callIt([!Callable()!]); +} +``` + +#### Common fixes + +Explicitly tear off the `call` method: + +```dart +class Callable { + void call() {} +} + +void callIt(void Function() f) { + f(); +} + +void f() { + callIt(Callable().call); +} +``` + +### invalid_use_of_do_not_submit_member + +_Uses of '{0}' should not be submitted to source control._ + +#### Description + +The analyzer produces this diagnostic when a member that is annotated with +[`@doNotSubmit`][meta-doNotSubmit] is referenced outside of a member +declaration that is also annotated with `@doNotSubmit`. + +#### Example + +Given a file `a.dart` containing the following declaration: + +```dart +import 'package:meta/meta.dart'; + +@doNotSubmit +void emulateCrash() { /* ... */ } +``` + +The following code produces this diagnostic because the declaration is +being referenced outside of a member that is also annotated with +`@doNotSubmit`: + +```dart +import 'a.dart'; + +void f() { + [!emulateCrash!](); +} +``` + +#### Common fixes + +Most commonly, when complete with local testing, the reference to the +member should be removed. + +If building additional functionality on top of the member, annotate the +newly added member with `@doNotSubmit` as well: + +```dart +import 'package:meta/meta.dart'; + +import 'a.dart'; + +@doNotSubmit +void emulateCrashWithOtherFunctionality() { + emulateCrash(); + // do other things. +} +``` + +### library_names + +_The library name '{0}' isn't a lower\_case\_with\_underscores identifier._ + +#### Description + +The analyzer produces this diagnostic when the name of a library doesn't +use the lower_case_with_underscores naming convention. + +#### Example + +The following code produces this diagnostic because the library name +`libraryName` isn't a lower_case_with_underscores identifier: + +```dart +library [!libraryName!]; +``` + +#### Common fixes + +If the library name is not required, then remove the library name: + +```dart +library; +``` + +If the library name is required, then convert it to use the +lower_case_with_underscores naming convention: + +```dart +library library_name; +``` + +### library_prefixes + +_The prefix '{0}' isn't a lower\_case\_with\_underscores identifier._ + +#### Description + +The analyzer produces this diagnostic when an import prefix doesn't use +the lower_case_with_underscores naming convention. + +#### Example + +The following code produces this diagnostic because the prefix +`ffiSupport` isn't a lower_case_with_underscores identifier: + +```dart +import 'package:ffi/ffi.dart' as [!ffiSupport!]; +``` + +#### Common fixes + +Convert the prefix to use the lower_case_with_underscores naming +convention: + +```dart +import 'package:ffi/ffi.dart' as ffi_support; +``` + +### library_private_types_in_public_api + +_Invalid use of a private type in a public API._ + +#### Description + +The analyzer produces this diagnostic when a type that is not part of the +public API of a library is referenced in the public API of that library. + +Using a private type in a public API can make the API unusable outside the +defining library. + +#### Example + +The following code produces this diagnostic because the parameter `c` of +the public function `f` has a type that is library private (`_C`): + +```dart +void f([!_C!] c) {} + +class _C {} +``` + +#### Common fixes + +If the API doesn't need to be used outside the defining library, then make +it private: + +```dart +void _f(_C c) {} + +class _C {} +``` + +If the API needs to be part of the public API of the library, then either +use a different type that's public, or make the referenced type public: + +```dart +void f(C c) {} + +class C {} +``` + +### literal_only_boolean_expressions + +_The Boolean expression has a constant value._ + +#### Description + +The analyzer produces this diagnostic when the value of the condition in +an `if` or loop statement is known to be either always `true` or always +`false`. An exception is made for a `while` loop whose condition is the +Boolean literal `true`. + +#### Examples + +The following code produces this diagnostic because the condition will +always evaluate to `true`: + +```dart +void f() { + [!if (true) {!] + [!print('true');!] + [!}!] +} +``` + +The lint will evaluate a subset of expressions that are composed of +constants, so the following code will also produce this diagnostic because +the condition will always evaluate to `false`: + +```dart +void g(int i) { + [!if (1 == 0 || 3 > 4) {!] + [!print('false');!] + [!}!] +} +``` + +#### Common fixes + +If the condition is wrong, then correct the condition so that it's value +can't be known at compile time: + +```dart +void g(int i) { + if (i == 0 || i > 4) { + print('false'); + } +} +``` + +If the condition is correct, then simplify the code to not evaluate the +condition: + +```dart +void f() { + print('true'); +} +``` + +### no_adjacent_strings_in_list + +_Don't use adjacent strings in a list literal._ + +#### Description + +The analyzer produces this diagnostic when two string literals are +adjacent in a list literal. Adjacent strings in Dart are concatenated +together to form a single string, but the intent might be for each string +to be a separate element in the list. + +#### Example + +The following code produces this diagnostic because the strings `'a'` and +`'b'` are adjacent: + +```dart +List list = [[!'a' 'b'!], 'c']; +``` + +#### Common fixes + +If the two strings are intended to be separate elements of the list, then +add a comma between them: + +```dart +List list = ['a', 'b', 'c']; +``` + +If the two strings are intended to be a single concatenated string, then +either manually merge the strings: + +```dart +List list = ['ab', 'c']; +``` + +Or use the `+` operator to concatenate the strings: + +```dart +List list = ['a' + 'b', 'c']; +``` + +### no_duplicate_case_values + +_The value of the case clause ('{0}') is equal to the value of an earlier case +clause ('{1}')._ + +#### Description + +The analyzer produces this diagnostic when two or more `case` clauses in +the same `switch` statement have the same value. + +Any `case` clauses after the first can't be executed, so having duplicate +`case` clauses is misleading. + +This diagnostic is often the result of either a typo or a change to the +value of a constant. + +#### Example + +The following code produces this diagnostic because two case clauses have +the same value (1): + +```dart +// @dart = 2.14 +void f(int v) { + switch (v) { + case 1: + break; + case [!1!]: + break; + } +} +``` + +#### Common fixes + +If one of the clauses should have a different value, then change the value +of the clause: + +```dart +void f(int v) { + switch (v) { + case 1: + break; + case 2: + break; + } +} +``` + +If the value is correct, then merge the statements into a single clause: + +```dart +void f(int v) { + switch (v) { + case 1: + break; + } +} +``` + +### no_leading_underscores_for_library_prefixes + +_The library prefix '{0}' starts with an underscore._ + +#### Description + +The analyzer produces this diagnostic when the name of a prefix declared +on an import starts with an underscore. + +Library prefixes are inherently not visible outside the declaring library, +so a leading underscore indicating private adds no value. + +#### Example + +The following code produces this diagnostic because the prefix `_core` +starts with an underscore: + +```dart +import 'dart:core' as [!_core!]; +``` + +#### Common fixes + +Remove the underscore: + +```dart +import 'dart:core' as core; +``` + +### no_leading_underscores_for_local_identifiers + +_The local variable '{0}' starts with an underscore._ + +#### Description + +The analyzer produces this diagnostic when the name of a local variable +starts with an underscore. + +Local variables are inherently not visible outside the declaring library, +so a leading underscore indicating private adds no value. + +#### Example + +The following code produces this diagnostic because the parameter `_s` +starts with an underscore: + +```dart +int f(String [!_s!]) => _s.length; +``` + +#### Common fixes + +Remove the underscore: + +```dart +int f(String s) => s.length; +``` + +### no_logic_in_create_state + +_Don't put any logic in 'createState'._ + +#### Description + +The analyzer produces this diagnostic when an implementation of +`createState` in a subclass of `StatefulWidget` contains any logic other +than the return of the result of invoking a zero argument constructor. + +#### Examples + +The following code produces this diagnostic because the constructor +invocation has arguments: + +```dart +import 'package:flutter/material.dart'; + +class MyWidget extends StatefulWidget { + @override + MyState createState() => [!MyState(0)!]; +} + +class MyState extends State { + int x; + + MyState(this.x); +} +``` + +#### Common fixes + +Rewrite the code so that `createState` doesn't contain any logic: + +```dart +import 'package:flutter/material.dart'; + +class MyWidget extends StatefulWidget { + @override + MyState createState() => MyState(); +} + +class MyState extends State { + int x = 0; + + MyState(); +} +``` + +### no_wildcard_variable_uses + +_The referenced identifier is a wildcard._ + +#### Description + +The analyzer produces this diagnostic when either a parameter or local +variable whose name consists of only underscores is referenced. Such +names will become non-binding in a future version of the Dart language, +making the reference illegal. + +#### Example + +The following code produces this diagnostic because the name of the +parameter consists of two underscores: + +```dart +void f(int __) { + print([!__!]); +} +``` + +The following code produces this diagnostic because the name of the +local variable consists of a single underscore: + +```dart +void f() { + int _ = 0; + print([!_!]); +} +``` + +#### Common fixes + +If the variable or parameter is intended to be referenced, then give it a +name that has at least one non-underscore character: + +```dart +void f(int p) { + print(p); +} +``` + +If the variable or parameter is not intended to be referenced, then +replace the reference with a different expression: + +```dart +void f() { + print(0); +} +``` + +### non_constant_identifier_names + +_The variable name '{0}' isn't a lowerCamelCase identifier._ + +#### Description + +The analyzer produces this diagnostic when the name of a class member, +top-level declaration, variable, parameter, named parameter, or named +constructor that isn't declared to be `const`, doesn't use the +lowerCamelCase convention. + +#### Example + +The following code produces this diagnostic because the top-level variable +`Count` doesn't start with a lowercase letter: + +```dart +var [!Count!] = 0; +``` + +#### Common fixes + +Change the name in the declaration to follow the lowerCamelCase +convention: + +```dart +var count = 0; +``` + +### null_check_on_nullable_type_parameter + +_The null check operator shouldn't be used on a variable whose type is a +potentially nullable type parameter._ + +#### Description + +The analyzer produces this diagnostic when a null check operator is used +on a variable whose type is `T?`, where `T` is a type parameter that +allows the type argument to be nullable (either has no bound or has a +bound that is nullable). + +Given a generic type parameter `T` which has a nullable bound, it is very +easy to introduce erroneous null checks when working with a variable of +type `T?`. Specifically, it is not uncommon to have `T? x;` and want to +assert that `x` has been set to a valid value of type `T`. A common +mistake is to do so using `x!`. This is almost always incorrect, because +if `T` is a nullable type, `x` may validly hold `null` as a value of type +`T`. + +#### Example + +The following code produces this diagnostic because `t` has the type `T?` +and `T` allows the type argument to be nullable (because it has no +`extends` clause): + +```dart +T f(T? t) => t[!!!]; +``` + +#### Common fixes + +Use the type parameter to cast the variable: + +```dart +T f(T? t) => t as T; +``` + +### overridden_fields + +_Field overrides a field inherited from '{0}'._ + +#### Description + +The analyzer produces this diagnostic when a class defines a field that +overrides a field from a superclass. + +Overriding a field with another field causes the object to have two +distinct fields, but because the fields have the same name only one of the +fields can be referenced in a given scope. That can lead to confusion +where a reference to one of the fields can be mistaken for a reference to +the other. + +#### Example + +The following code produces this diagnostic because the field `f` in `B` +shadows the field `f` in `A`: + +```dart +class A { + int f = 1; +} + +class B extends A { + @override + int [!f!] = 2; +} +``` + +#### Common fixes + +If the two fields are representing the same property, then remove the +field from the subclass: + +```dart +class A { + int f = 1; +} + +class B extends A {} +``` + +If the two fields should be distinct, then rename one of the fields: + +```dart +class A { + int f = 1; +} + +class B extends A { + int g = 2; +} +``` + +If the two fields are related in some way, but can't be the same, then +find a different way to implement the semantics you need. + +### package_names + +_The package name '{0}' isn't a lower\_case\_with\_underscores identifier._ + +#### Description + +The analyzer produces this diagnostic when the name of a package doesn't +use the lower_case_with_underscores naming convention. + +#### Example + +The following code produces this diagnostic because the name of the +package uses the lowerCamelCase naming convention: + +```yaml +name: [!somePackage!] +``` + +#### Common fixes + +Rewrite the name of the package using the lower_case_with_underscores +naming convention: + +```yaml +name: some_package +``` + +### package_prefixed_library_names + +_The library name is not a dot-separated path prefixed by the package name._ + +#### Description + +The analyzer produces this diagnostic when a library has a name that +doesn't follow these guidelines: + +- Prefix all library names with the package name. +- Make the entry library have the same name as the package. +- For all other libraries in a package, after the package name add the + dot-separated path to the library's Dart file. +- For libraries under `lib`, omit the top directory name. + +For example, given a package named `my_package`, here are the library +names for various files in the package: + + +#### Example + +Assuming that the file containing the following code is not in a file +named `special.dart` in the `lib` directory of a package named `something` +(which would be an exception to the rule), the analyzer produces this +diagnostic because the name of the library doesn't conform to the +guidelines above: + +```dart +library [!something.special!]; +``` + +#### Common fixes + +Change the name of the library to conform to the guidelines. + +### prefer_adjacent_string_concatenation + +_String literals shouldn't be concatenated by the '+' operator._ + +#### Description + +The analyzer produces this diagnostic when the `+` operator is used to +concatenate two string literals. + +#### Example + +The following code produces this diagnostic because two string literals +are being concatenated by using the `+` operator: + +```dart +var s = 'a' [!+!] 'b'; +``` + +#### Common fixes + +Remove the operator: + +```dart +var s = 'a' 'b'; +``` + +### prefer_collection_literals + +_Unnecessary constructor invocation._ + +#### Description + +The analyzer produces this diagnostic when a constructor is used to create +a list, map, or set, but a literal would produce the same result. + +#### Example + +The following code produces this diagnostic because the constructor for +`Map` is being used to create a map that could also be created using a +literal: + +```dart +var m = [!Map()!]; +``` + +#### Common fixes + +Use the literal representation: + +```dart +var m = {}; +``` + +### prefer_conditional_assignment + +_The 'if' statement could be replaced by a null-aware assignment._ + +#### Description + +The analyzer produces this diagnostic when an assignment to a variable is +conditional based on whether the variable has the value `null` and the +`??=` operator could be used instead. + +#### Example + +The following code produces this diagnostic because the parameter `s` is +being compared to `null` in order to determine whether to assign a +different value: + +```dart +int f(String? s) { + [!if (s == null) {!] + [!s = '';!] + [!}!] + return s.length; +} +``` + +#### Common fixes + +Use the `??=` operator instead of an explicit `if` statement: + +```dart +int f(String? s) { + s ??= ''; + return s.length; +} +``` + +### prefer_const_constructors + +_Use 'const' with the constructor to improve performance._ + +#### Description + +The analyzer produces this diagnostic when an invocation of a const +constructor isn't either preceded by `const` or in a [constant context][]. + +#### Example + +The following code produces this diagnostic because the invocation of the +`const` constructor is neither prefixed by `const` nor in a +[constant context][]: + +```dart +class C { + const C(); +} + +C c = [!C()!]; +``` + +#### Common fixes + +If the context can be made a [constant context][], then do so: + +```dart +class C { + const C(); +} + +const C c = C(); +``` + +If the context can't be made a [constant context][], then add `const` +before the constructor invocation: + +```dart +class C { + const C(); +} + +C c = const C(); +``` + +### prefer_const_constructors_in_immutables + +_Constructors in '@immutable' classes should be declared as 'const'._ + +#### Description + +The analyzer produces this diagnostic when a non-`const` constructor is +found in a class that has the `@immutable` annotation. + +#### Example + +The following code produces this diagnostic because the constructor in `C` +isn't declared as `const` even though `C` has the `@immutable` annotation: + +```dart +import 'package:meta/meta.dart'; + +@immutable +class C { + final f; + + [!C!](this.f); +} +``` + +#### Common fixes + +If the class really is intended to be immutable, then add the `const` +modifier to the constructor: + +```dart +import 'package:meta/meta.dart'; + +@immutable +class C { + final f; + + const C(this.f); +} +``` + +If the class is mutable, then remove the `@immutable` annotation: + +```dart +class C { + final f; + + C(this.f); +} +``` + +### prefer_const_declarations + +_Use 'const' for final variables initialized to a constant value._ + +#### Description + +The analyzer produces this diagnostic when a top-level variable, static +field, or local variable is marked as `final` and is initialized to a +constant value. + +#### Examples + +The following code produces this diagnostic because the top-level variable +`v` is both `final` and initialized to a constant value: + +```dart +[!final v = const []!]; +``` + +The following code produces this diagnostic because the static field `f` +is both `final` and initialized to a constant value: + +```dart +class C { + static [!final f = const []!]; +} +``` + +The following code produces this diagnostic because the local variable `v` +is both `final` and initialized to a constant value: + +```dart +void f() { + [!final v = const []!]; + print(v); +} +``` + +#### Common fixes + +Replace the keyword `final` with `const` and remove `const` from the +initializer: + +```dart +class C { + static const f = []; +} +``` + +### prefer_const_literals_to_create_immutables + +_Use 'const' literals as arguments to constructors of '@immutable' classes._ + +#### Description + +The analyzer produces this diagnostic when a non-const list, map, or set +literal is passed as an argument to a constructor declared in a class +annotated with `@immutable`. + +#### Example + +The following code produces this diagnostic because the list literal +(`[1]`) is being passed to a constructor in an immutable class but isn't +a constant list: + +```dart +import 'package:meta/meta.dart'; + +@immutable +class C { + final f; + + const C(this.f); +} + +C c = C([![1]!]); +``` + +#### Common fixes + +If the context can be made a [constant context][], then do so: + +```dart +import 'package:meta/meta.dart'; + +@immutable +class C { + final f; + + const C(this.f); +} + +const C c = C([1]); +``` + +If the context can't be made a [constant context][] but the constructor +can be invoked using `const`, then add `const` before the constructor +invocation: + +```dart +import 'package:meta/meta.dart'; + +@immutable +class C { + final f; + + const C(this.f); +} + +C c = const C([1]); +``` + +If the context can't be made a [constant context][] and the constructor +can't be invoked using `const`, then add the keyword `const` before the +collection literal: + +```dart +import 'package:meta/meta.dart'; + +@immutable +class C { + final f; + + const C(this.f); +} + +C c = C(const [1]); +``` + +### prefer_contains + +_Always false because indexOf is always greater or equal -1._ + +_Always true because indexOf is always greater or equal -1._ + +_Unnecessary use of 'indexOf' to test for containment._ + +#### Description + +The analyzer produces this diagnostic when the method `indexOf` is used and +the result is only compared with `-1` or `0` in a way where the semantics +are equivalent to using `contains`. + +#### Example + +The following code produces this diagnostic because the condition in the +`if` statement is checking to see whether the list contains the string: + +```dart +void f(List l, String s) { + if ([!l.indexOf(s) < 0!]) { + // ... + } +} +``` + +#### Common fixes + +Use `contains` instead, negating the condition when necessary: + +```dart +void f(List l, String s) { + if (l.contains(s)) { + // ... + } +} +``` + +### prefer_final_fields + +_The private field {0} could be 'final'._ + +#### Description + +The analyzer produces this diagnostic when a private field is only +assigned one time. The field can be initialized in multiple constructors +and still be flagged because only one of those constructors can ever run. + +#### Example + +The following code produces this diagnostic because the field `_f` is only +assigned one time, in the field's initializer: + +```dart +class C { + int [!_f = 1!]; + + int get f => _f; +} +``` + +#### Common fixes + +Mark the field `final`: + +```dart +class C { + final int _f = 1; + + int get f => _f; +} +``` + +### prefer_for_elements_to_map_fromiterable + +_Use 'for' elements when building maps from iterables._ + +#### Description + +The analyzer produces this diagnostic when `Map.fromIterable` is used to +build a map that could be built using the `for` element. + +#### Example + +The following code produces this diagnostic because `fromIterable` is +being used to build a map that could be built using a `for` element: + +```dart +void f(Iterable data) { + [!Map.fromIterable(!] + [!data,!] + [!key: (element) => element,!] + [!value: (element) => element.length,!] + [!)!]; +} +``` + +#### Common fixes + +Use a `for` element to build the map: + +```dart +void f(Iterable data) { + { + for (var element in data) + element: element.length + }; +} +``` + +### prefer_function_declarations_over_variables + +_Use a function declaration rather than a variable assignment to bind a function +to a name._ + +#### Description + +The analyzer produces this diagnostic when a closure is assigned to a +local variable and the local variable is not re-assigned anywhere. + +#### Example + +The following code produces this diagnostic because the local variable `f` +is initialized to be a closure and isn't assigned any other value: + +```dart +void g() { + var [!f = (int i) => i * 2!]; + f(1); +} +``` + +#### Common fixes + +Replace the local variable with a local function: + +```dart +void g() { + int f(int i) => i * 2; + f(1); +} +``` + +### prefer_generic_function_type_aliases + +_Use the generic function type syntax in 'typedef's._ + +#### Description + +The analyzer produces this diagnostic when a typedef is written using the +older syntax for function type aliases in which the name being declared is +embedded in the function type. + +#### Example + +The following code produces this diagnostic because it uses the older +syntax: + +```dart +typedef void [!F!](); +``` + +#### Common fixes + +Rewrite the typedef to use the newer syntax: + +```dart +typedef F = void Function(); +``` + +### prefer_if_null_operators + +_Use the '??' operator rather than '?:' when testing for 'null'._ + +#### Description + +The analyzer produces this diagnostic when a conditional expression (using +the `?:` operator) is used to select a different value when a local +variable is `null`. + +#### Example + +The following code produces this diagnostic because the variable `s` is +being compared to `null` so that a different value can be returned when +`s` is `null`: + +```dart +String f(String? s) => [!s == null ? '' : s!]; +``` + +#### Common fixes + +Use the if-null operator instead: + +```dart +String f(String? s) => s ?? ''; +``` + +### prefer_initializing_formals + +_Use an initializing formal to assign a parameter to a field._ + +#### Description + +The analyzer produces this diagnostic when a constructor parameter is used +to initialize a field without modification. + +#### Example + +The following code produces this diagnostic because the parameter `c` is +only used to set the field `c`: + +```dart +class C { + int c; + + C(int c) : [!this.c = c!]; +} +``` + +#### Common fixes + +Use an initializing formal parameter to initialize the field: + +```dart +class C { + int c; + + C(this.c); +} +``` + +### prefer_inlined_adds + +_The addition of a list item could be inlined._ + +_The addition of multiple list items could be inlined._ + +#### Description + +The analyzer produces this diagnostic when the methods `add` and `addAll` +are invoked on a list literal where the elements being added could be +included in the list literal. + +#### Example + +The following code produces this diagnostic because the `add` method is +being used to add `b`, when it could have been included directly in the +list literal: + +```dart +List f(String a, String b) { + return [a]..[!add!](b); +} +``` + +The following code produces this diagnostic because the `addAll` method is +being used to add the elements of `b`, when it could have been included +directly in the list literal: + +```dart +List f(String a, List b) { + return [a]..[!addAll!](b); +} +``` + +#### Common fixes + +If the `add` method is being used, then make the argument an element of +the list and remove the invocation: + +```dart +List f(String a, String b) { + return [a, b]; +} +``` + +If the `addAll` method is being used, then use the spread operator on the +argument to add its elements to the list and remove the invocation: + +```dart +List f(String a, List b) { + return [a, ...b]; +} +``` + +### prefer_interpolation_to_compose_strings + +_Use interpolation to compose strings and values._ + +#### Description + +The analyzer produces this diagnostic when string literals and computed +strings are being concatenated using the `+` operator, but string +interpolation would achieve the same result. + +#### Example + +The following code produces this diagnostic because the elements of the +list `l` are being concatenated with other strings using the `+` operator: + +```dart +String f(List l) { + return [!'(' + l[0] + ', ' + l[1] + ')'!]; +} +``` + +#### Common fixes + +Use string interpolation: + +```dart +String f(List l) { + return '(${l[0]}, ${l[1]})'; +} +``` + +### prefer_is_empty + +_The comparison is always 'false' because the length is always greater than or +equal to 0._ + +_The comparison is always 'true' because the length is always greater than or +equal to 0._ + +_Use 'isEmpty' instead of 'length' to test whether the collection is empty._ + +_Use 'isNotEmpty' instead of 'length' to test whether the collection is empty._ + +#### Description + +The analyzer produces this diagnostic when the result of invoking either +`Iterable.length` or `Map.length` is compared for equality with zero +(`0`). + +#### Example + +The following code produces this diagnostic because the result of invoking +`length` is checked for equality with zero: + +```dart +int f(Iterable p) => [!p.length == 0!] ? 0 : p.first; +``` + +#### Common fixes + +Replace the use of `length` with a use of either `isEmpty` or +`isNotEmpty`: + +```dart +void f(Iterable p) => p.isEmpty ? 0 : p.first; +``` + +### prefer_is_not_empty + +_Use 'isNotEmpty' rather than negating the result of 'isEmpty'._ + +#### Description + +The analyzer produces this diagnostic when the result of invoking +`Iterable.isEmpty` or `Map.isEmpty` is negated. + +#### Example + +The following code produces this diagnostic because the result of invoking +`Iterable.isEmpty` is negated: + +```dart +void f(Iterable p) => [!!p.isEmpty!] ? p.first : 0; +``` + +#### Common fixes + +Rewrite the code to use `isNotEmpty`: + +```dart +void f(Iterable p) => p.isNotEmpty ? p.first : 0; +``` + +### prefer_is_not_operator + +_Use the 'is!' operator rather than negating the value of the 'is' operator._ + +#### Description + +The analyzer produces this diagnostic when the prefix `!` operator is used +to negate the result of an `is` test. + +#### Example + +The following code produces this diagnostic because the result of testing +to see whether `o` is a `String` is negated using the prefix `!` operator: + +```dart +String f(Object o) { + if ([!!(o is String)!]) { + return o.toString(); + } + return o; +} +``` + +#### Common fixes + +Use the `is!` operator instead: + +```dart +String f(Object o) { + if (o is! String) { + return o.toString(); + } + return o; +} +``` + +### prefer_iterable_wheretype + +_Use 'whereType' to select elements of a given type._ + +#### Description + +The analyzer produces this diagnostic when the method `Iterable.where` is +being used to filter elements based on their type. + +#### Example + +The following code produces this diagnostic because the method `where` is +being used to access only the strings within the iterable: + +```dart +Iterable f(Iterable p) => p.[!where!]((e) => e is String); +``` + +#### Common fixes + +Rewrite the code to use `whereType`: + +```dart +Iterable f(Iterable p) => p.whereType(); +``` + +This might also allow you to tighten the types in your code or remove +other type checks. + +### prefer_null_aware_operators + +_Use the null-aware operator '?.' rather than an explicit 'null' comparison._ + +#### Description + +The analyzer produces this diagnostic when a comparison with `null` is +used to guard a member reference, and `null` is used as a result when the +guarded target is `null`. + +#### Example + +The following code produces this diagnostic because the invocation of +`length` is guarded by a `null` comparison even though the default value +is `null`: + +```dart +int? f(List? p) { + return [!p == null ? null : p.length!]; +} +``` + +#### Common fixes + +Use a null-aware access operator instead: + +```dart +int? f(List? p) { + return p?.length; +} +``` + +### prefer_relative_imports + +_Use relative imports for files in the 'lib' directory._ + +#### Description + +The analyzer produces this diagnostic when an `import` in a library inside +the `lib` directory uses a `package:` URI to refer to another library in +the same package. + +#### Example + +The following code produces this diagnostic because it uses a `package:` +URI when a relative URI could have been used: + +```dart +import 'package:my_package/bar.dart'; +``` + +#### Common fixes + +Use a relative URI to import the library: + +```dart +import 'bar.dart'; +``` + +### prefer_typing_uninitialized_variables + +_Prefer typing uninitialized variables and fields._ + +#### Description + +The analyzer produces this diagnostic when a variable without an +initializer doesn't have an explicit type annotation. + +Without either a type annotation or an initializer, a variable has the +type `dynamic`, which allows any value to be assigned to the variable, +often causing hard to identify bugs. + +#### Example + +The following code produces this diagnostic because the variable `r` +doesn't have either a type annotation or an initializer: + +```dart +Object f() { + var [!r!]; + r = ''; + return r; +} +``` + +#### Common fixes + +If the variable can be initialized, then add an initializer: + +```dart +Object f() { + var r = ''; + return r; +} +``` + +If the variable can't be initialized, then add an explicit type +annotation: + +```dart +Object f() { + String r; + r = ''; + return r; +} +``` + +### prefer_void_to_null + +_Unnecessary use of the type 'Null'._ + +#### Description + +The analyzer produces this diagnostic when `Null` is used in a location +where `void` would be a valid choice. + +#### Example + +The following code produces this diagnostic because the function `f` is +declared to return `null` (at some future time): + +```dart +Future<[!Null!]> f() async {} +``` + +#### Common fixes + +Replace the use of `Null` with a use of `void`: + +```dart +Future f() async {} +``` + +### provide_deprecation_message + +_Missing a deprecation message._ + +#### Description + +The analyzer produces this diagnostic when a `deprecated` annotation is +used instead of the `Deprecated` annotation. + +#### Example + +The following code produces this diagnostic because the function `f` is +annotated with `deprecated`: + +```dart +[!@deprecated!] +void f() {} +``` + +#### Common fixes + +Convert the code to use the longer form: + +```dart +@Deprecated('Use g instead. Will be removed in 4.0.0.') +void f() {} +``` + +### recursive_getters + +_The getter '{0}' recursively returns itself._ + +#### Description + +The analyzer produces this diagnostic when a getter invokes itself, +resulting in an infinite loop. + +#### Example + +The following code produces this diagnostic because the getter `count` +invokes itself: + +```dart +class C { + int _count = 0; + + int get [!count!] => count; +} +``` + +#### Common fixes + +Change the getter to not invoke itself: + +```dart +class C { + int _count = 0; + + int get count => _count; +} +``` + +### secure_pubspec_urls + +_The '{0}' protocol shouldn't be used because it isn't secure._ + +#### Description + +The analyzer produces this diagnostic when a URL in a `pubspec.yaml` file is +using a non-secure scheme, such as `http`. + +#### Example + +The following code produces this diagnostic because the `pubspec.yaml` file +contains an `http` URL: + +```yaml +dependencies: + example: any + repository: [!http://github.com/dart-lang/example!] +``` + +#### Common fixes + +Change the scheme of the URL to use a secure scheme, such as `https`: + +```yaml +dependencies: + example: any + repository: https://github.com/dart-lang/example +``` + +### sized_box_for_whitespace + +_Use a 'SizedBox' to add whitespace to a layout._ + +#### Description + +The analyzer produces this diagnostic when a `Container` is created using +only the `height` and/or `width` arguments. + +#### Example + +The following code produces this diagnostic because the `Container` has +only the `width` argument: + +```dart +import 'package:flutter/material.dart'; + +Widget buildRow() { + return Row( + children: [ + const Text('...'), + [!Container!]( + width: 4, + child: Text('...'), + ), + const Expanded( + child: Text('...'), + ), + ], + ); +} +``` + +#### Common fixes + +Replace the `Container` with a `SizedBox` of the same dimensions: + +```dart +import 'package:flutter/material.dart'; + +Widget buildRow() { + return Row( + children: [ + Text('...'), + SizedBox( + width: 4, + child: Text('...'), + ), + Expanded( + child: Text('...'), + ), + ], + ); +} +``` + +### slash_for_doc_comments + +_Use the end-of-line form ('///') for doc comments._ + +#### Description + +The analyzer produces this diagnostic when a documentation comment uses +the block comment style (delimited by `/**` and `*/`). + +#### Example + +The following code produces this diagnostic because the documentation +comment for `f` uses a block comment style: + +```dart +[!/**!] +[! * Example.!] +[! */!] +void f() {} +``` + +#### Common fixes + +Use an end-of-line comment style: + +```dart +/// Example. +void f() {} +``` + +### sort_child_properties_last + +_The '{0}' argument should be last in widget constructor invocations._ + +#### Description + +The analyzer produces this diagnostic when the `child` or `children` +argument isn't the last argument in an invocation of a widget class' +constructor. An exception is made if all of the arguments after the +`child` or `children` argument are function expressions. + +#### Example + +The following code produces this diagnostic because the `child` argument +isn't the last argument in the invocation of the `Center` constructor: + +```dart +import 'package:flutter/material.dart'; + +Widget createWidget() { + return Center( + [!child: Text('...')!], + widthFactor: 0.5, + ); +} +``` + +#### Common fixes + +Move the `child` or `children` argument to be last: + +```dart +import 'package:flutter/material.dart'; + +Widget createWidget() { + return Center( + widthFactor: 0.5, + child: Text('...'), + ); +} +``` + +### sort_pub_dependencies + +_Dependencies not sorted alphabetically._ + +#### Description + +The analyzer produces this diagnostic when the keys in a dependency map in +the `pubspec.yaml` file aren't sorted alphabetically. The dependency maps +that are checked are the `dependencies`, `dev_dependencies`, and +`dependency_overrides` maps. + +#### Example + +The following code produces this diagnostic because the entries in the +`dependencies` map are not sorted: + +```yaml +dependencies: + path: any + collection: any +``` + +#### Common fixes + +Sort the entries: + +```yaml +dependencies: + collection: any + path: any +``` + +### test_types_in_equals + +_Missing type test for '{0}' in '=='._ + +#### Description + +The analyzer produces this diagnostic when an override of the `==` +operator doesn't include a type test on the value of the parameter. + +#### Example + +The following code produces this diagnostic because `other` is not type +tested: + +```dart +class C { + final int f; + + C(this.f); + + @override + bool operator ==(Object other) { + return ([!other as C!]).f == f; + } +} +``` + +#### Common fixes + +Perform an `is` test as part of computing the return value: + +```dart +class C { + final int f; + + C(this.f); + + @override + bool operator ==(Object other) { + return other is C && other.f == f; + } +} +``` + +### throw_in_finally + +_Use of '{0}' in 'finally' block._ + +#### Description + +The analyzer produces this diagnostic when a `throw` statement is found +inside a `finally` block. + +#### Example + +The following code produces this diagnostic because there is a `throw` +statement inside a `finally` block: + +```dart +void f() { + try { + // ... + } catch (e) { + // ... + } finally { + [!throw 'error'!]; + } +} +``` + +#### Common fixes + +Rewrite the code so that the `throw` statement isn't inside a `finally` +block: + +```dart +void f() { + try { + // ... + } catch (e) { + // ... + } + throw 'error'; +} +``` + +### type_init_formals + +_Don't needlessly type annotate initializing formals._ + +#### Description + +The analyzer produces this diagnostic when an initializing formal +parameter (`this.x`) or a super parameter (`super.x`) has an explicit type +annotation that is the same as the field or overridden parameter. + +If a constructor parameter is using `this.x` to initialize a field, then +the type of the parameter is implicitly the same type as the field. If a +constructor parameter is using `super.x` to forward to a super +constructor, then the type of the parameter is implicitly the same as the +super constructor parameter. + +#### Example + +The following code produces this diagnostic because the parameter `this.c` +has an explicit type that is the same as the field `c`: + +```dart +class C { + int c; + + C([!int!] this.c); +} +``` + +The following code produces this diagnostic because the parameter +`super.a` has an explicit type that is the same as the parameter `a` from +the superclass: + +```dart +class A { + A(int a); +} + +class B extends A { + B([!int!] super.a); +} +``` + +#### Common fixes + +Remove the type annotation from the parameter: + +```dart +class C { + int c; + + C(this.c); +} +``` + +### type_literal_in_constant_pattern + +_Use 'TypeName \_' instead of a type literal._ + +#### Description + +The analyzer produces this diagnostic when a type literal appears as a +pattern. + +#### Example + +The following code produces this diagnostic because a type literal is used +as a constant pattern: + +```dart +void f(Object? x) { + if (x case [!num!]) { + // ... + } +} +``` + +#### Common fixes + +If the type literal is intended to match an object of the given type, then +use either a variable pattern: + +```dart +void f(Object? x) { + if (x case num _) { + // ... + } +} +``` + +Or an object pattern: + +```dart +void f(Object? x) { + if (x case num()) { + // ... + } +} +``` + +If the type literal is intended to match the type literal, then write it +as a constant pattern: + +```dart +void f(Object? x) { + if (x case const (num)) { + // ... + } +} +``` + +### unnecessary_brace_in_string_interps + +_Unnecessary braces in a string interpolation._ + +#### Description + +The analyzer produces this diagnostic when a string interpolation with +braces is used to interpolate a simple identifier and isn't followed by +alphanumeric text. + +#### Example + +The following code produces this diagnostic because the interpolation +element `${s}` uses braces when they are not necessary: + +```dart +String f(String s) { + return '"[!${s}!]"'; +} +``` + +#### Common fixes + +Remove the unnecessary braces: + +```dart +String f(String s) { + return '"$s"'; +} +``` + +### unnecessary_const + +_Unnecessary 'const' keyword._ + +#### Description + +The analyzer produces this diagnostic when the keyword `const` is used in +a [constant context][]. The keyword isn't required because it's implied. + +#### Example + +The following code produces this diagnostic because the keyword `const` in +the list literal isn't needed: + +```dart +const l = [!const!] []; +``` + +The list is implicitly `const` because of the keyword `const` on the +variable declaration. + +#### Common fixes + +Remove the unnecessary keyword: + +```dart +const l = []; +``` + +### unnecessary_constructor_name + +_Unnecessary '.new' constructor name._ + +#### Description + +The analyzer produces this diagnostic when a reference to an unnamed +constructor uses `.new`. The only place where `.new` is required is in a +constructor tear-off. + +#### Example + +The following code produces this diagnostic because `.new` is being used +to refer to the unnamed constructor where it isn't required: + +```dart +var o = Object.[!new!](); +``` + +#### Common fixes + +Remove the unnecessary `.new`: + +```dart +var o = Object(); +``` + +### unnecessary_getters_setters + +_Unnecessary use of getter and setter to wrap a field._ + +#### Description + +The analyzer produces this diagnostic when a getter and setter pair +returns and sets the value of a field without any additional processing. + +#### Example + +The following code produces this diagnostic because the getter/setter pair +named `c` only expose the field named `_c`: + +```dart +class C { + int? _c; + + int? get [!c!] => _c; + + set c(int? v) => _c = v; +} +``` + +#### Common fixes + +Make the field public and remove the getter and setter: + +```dart +class C { + int? c; +} +``` + +### unnecessary_late + +_Unnecessary 'late' modifier._ + +#### Description + +The analyzer produces this diagnostic when a top-level variable or static +field with an initializer is marked as `late`. Top-level variables and +static fields are implicitly late, so they don't need to be explicitly +marked. + +#### Example + +The following code produces this diagnostic because the static field `c` +has the modifier `late` even though it has an initializer: + +```dart +class C { + static [!late!] String c = ''; +} +``` + +#### Common fixes + +Remove the keyword `late`: + +```dart +class C { + static String c = ''; +} +``` + +### unnecessary_new + +_Unnecessary 'new' keyword._ + +#### Description + +The analyzer produces this diagnostic when the keyword `new` is used to +invoke a constructor. + +#### Example + +The following code produces this diagnostic because the keyword `new` is +used to invoke the unnamed constructor from `Object`: + +```dart +var o = [!new!] Object(); +``` + +#### Common fixes + +Remove the keyword `new`: + +```dart +var o = Object(); +``` + +### unnecessary_null_aware_assignments + +_Unnecessary assignment of 'null'._ + +#### Description + +The analyzer produces this diagnostic when the right-hand side of a +null-aware assignment is the `null` literal. + +#### Example + +The following code produces this diagnostic because the null aware +operator is being used to assign `null` to `s` when `s` is already `null`: + +```dart +void f(String? s) { + [!s ??= null!]; +} +``` + +#### Common fixes + +If a non-null value should be assigned to the left-hand operand, then +change the right-hand side: + +```dart +void f(String? s) { + s ??= ''; +} +``` + +If there is no non-null value to assign to the left-hand operand, then +remove the assignment: + +```dart +void f(String? s) { +} +``` + +### unnecessary_null_in_if_null_operators + +_Unnecessary use of '??' with 'null'._ + +#### Description + +The analyzer produces this diagnostic when the right operand of the `??` +operator is the literal `null`. + +#### Example + +The following code produces this diagnostic because the right-hand operand +of the `??` operator is `null`: + +```dart +String? f(String? s) => s ?? [!null!]; +``` + +#### Common fixes + +If a non-null value should be used for the right-hand operand, then +change the right-hand side: + +```dart +String f(String? s) => s ?? ''; +``` + +If there is no non-null value to use for the right-hand operand, then +remove the operator and the right-hand operand: + +```dart +String? f(String? s) => s; +``` + +### unnecessary_nullable_for_final_variable_declarations + +_Type could be non-nullable._ + +#### Description + +The analyzer produces this diagnostic when a final field or variable has a +nullable type but is initialized to a non-nullable value. + +#### Example + +The following code produces this diagnostic because the final variable `i` +has a nullable type (`int?`), but can never be `null`: + +```dart +final int? [!i!] = 1; +``` + +#### Common fixes + +Make the type non-nullable: + +```dart +final int i = 1; +``` + +### unnecessary_overrides + +_Unnecessary override._ + +#### Description + +The analyzer produces this diagnostic when an instance member overrides an +inherited member but only invokes the overridden member with exactly the +same arguments. + +#### Example + +The following code produces this diagnostic because the method `D.m` +doesn't do anything other than invoke the overridden method: + +```dart +class C { + int m(int x) => x; +} + +class D extends C { + @override + int [!m!](int x) => super.m(x); +} +``` + +#### Common fixes + +If the method should do something more than what the overridden method +does, then implement the missing functionality: + +```dart +class C { + int m(int x) => x; +} + +class D extends C { + @override + int m(int x) => super.m(x) + 1; +} +``` + +If the overridden method should be modified by changing the return type or +one or more of the parameter types, making one of the parameters +`covariant`, having a documentation comment, or by having additional +annotations, then update the code: + +```dart +import 'package:meta/meta.dart'; + +class C { + int m(int x) => x; +} + +class D extends C { + @mustCallSuper + @override + int m(int x) => super.m(x); +} +``` + +If the overriding method doesn't change or enhance the semantics of the +code, then remove it: + +```dart +class C { + int m(int x) => x; +} + +class D extends C {} +``` + +### unnecessary_statements + +_Unnecessary statement._ + +#### Description + +The analyzer produces this diagnostic when an expression statement has no +clear effect. + +#### Example + +The following code produces this diagnostic because the addition of the +returned values from the two invocations has no clear effect: + +```dart +void f(int Function() first, int Function() second) { + [!first() + second()!]; +} +``` + +#### Common fixes + +If the expression doesn't need to be computed, then remove it: + +```dart +void f(int Function() first, int Function() second) { +} +``` + +If the value of the expression is needed, then make use of it, possibly +assigning it to a local variable first: + +```dart +void f(int Function() first, int Function() second) { + print(first() + second()); +} +``` + +If portions of the expression need to be executed, then remove the +unnecessary portions: + +```dart +void f(int Function() first, int Function() second) { + first(); + second(); +} +``` + +### unnecessary_string_escapes + +_Unnecessary escape in string literal._ + +#### Description + +The analyzer produces this diagnostic when characters in a string are +escaped when escaping them is unnecessary. + +#### Example + +The following code produces this diagnostic because single quotes don't +need to be escaped inside strings delimited by double quotes: + +```dart +var s = "Don[!\!]'t use a backslash here."; +``` + +#### Common fixes + +Remove the unnecessary backslashes: + +```dart +var s = "Don't use a backslash here."; +``` + +### unnecessary_string_interpolations + +_Unnecessary use of string interpolation._ + +#### Description + +The analyzer produces this diagnostic when a string literal contains a +single interpolation of a `String`-valued variable and no other +characters. + +#### Example + +The following code produces this diagnostic because the string literal +contains a single interpolation and doesn't contain any character outside +the interpolation: + +```dart +String f(String s) => [!'$s'!]; +``` + +#### Common fixes + +Replace the string literal with the content of the interpolation: + +```dart +String f(String s) => s; +``` + +### unnecessary_this + +_Unnecessary 'this.' qualifier._ + +#### Description + +The analyzer produces this diagnostic when the keyword `this` is used to +access a member that isn't shadowed. + +#### Example + +The following code produces this diagnostic because the use of `this` to +access the field `_f` isn't necessary: + +```dart +class C { + int _f = 2; + + int get f => [!this!]._f; +} +``` + +#### Common fixes + +Remove the `this.`: + +```dart +class C { + int _f = 2; + + int get f => _f; +} +``` + +### unnecessary_to_list_in_spreads + +_Unnecessary use of 'toList' in a spread._ + +#### Description + +The analyzer produces this diagnostic when `toList` is used to convert an +`Iterable` to a `List` just before a spread operator is applied to the +list. The spread operator can be applied to any `Iterable`, so the +conversion isn't necessary. + +#### Example + +The following code produces this diagnostic because `toList` is invoked on +the result of `map`, which is an `Iterable` that the spread operator could +be applied to directly: + +```dart +List toLowercase(List strings) { + return [ + ...strings.map((String s) => s.toLowerCase()).[!toList!](), + ]; +} +``` + +#### Common fixes + +Remove the invocation of `toList`: + +```dart +List toLowercase(List strings) { + return [ + ...strings.map((String s) => s.toLowerCase()), + ]; +} +``` + +### unrelated_type_equality_checks + +_The type of the operand ('{0}') isn't a subtype or a supertype of the value +being matched ('{1}')._ + +_The type of the right operand ('{0}') isn't a subtype or a supertype of the +left operand ('{1}')._ + +#### Description + +The analyzer produces this diagnostic when two objects are being compared +and neither of the static types of the two objects is a subtype of the +other. + +Such a comparison will usually return `false` and might not reflect the +programmer's intent. + +There can be false positives. For example, a class named `Point` might +have subclasses named `CartesianPoint` and `PolarPoint`, neither of which +is a subtype of the other, but it might still be appropriate to test the +equality of instances. + +As a concrete case, the classes `Int64` and `Int32` from `package:fixnum` +allow comparing instances to an `int` provided the `int` is on the +right-hand side. This case is specifically allowed by the diagnostic, but +other such cases are not. + +#### Example + +The following code produces this diagnostic because the string `s` is +being compared to the integer `1`: + +```dart +bool f(String s) { + return s [!==!] 1; +} +``` + +#### Common fixes + +Replace one of the operands with something compatible with the other +operand: + +```dart +bool f(String s) { + return s.length == 1; +} +``` + +### use_build_context_synchronously + +_Don't use 'BuildContext's across async gaps, guarded by an unrelated 'mounted' +check._ + +_Don't use 'BuildContext's across async gaps._ + +#### Description + +The analyzer produces this diagnostic when a `BuildContext` is referenced +by a `StatefulWidget` after an asynchronous gap without first checking the +`mounted` property. + +Storing a `BuildContext` for later use can lead to difficult to diagnose +crashes. Asynchronous gaps implicitly store a `BuildContext`, making them +easy to overlook for diagnosis. + +#### Example + +The following code produces this diagnostic because the `context` is +passed to a constructor after the `await`: + +```dart +import 'package:flutter/material.dart'; + +class MyWidget extends Widget { + void onButtonTapped(BuildContext context) async { + await Future.delayed(const Duration(seconds: 1)); + Navigator.of([!context!]).pop(); + } +} +``` + +#### Common fixes + +If you can remove the asynchronous gap, do so: + +```dart +import 'package:flutter/material.dart'; + +class MyWidget extends Widget { + void onButtonTapped(BuildContext context) { + Navigator.of(context).pop(); + } +} +``` + +If you can't remove the asynchronous gap, then use `mounted` to guard the +use of the `context`: + +```dart +import 'package:flutter/material.dart'; + +class MyWidget extends Widget { + void onButtonTapped(BuildContext context) async { + await Future.delayed(const Duration(seconds: 1)); + if (context.mounted) { + Navigator.of(context).pop(); + } + } +} +``` + +### use_full_hex_values_for_flutter_colors + +_Instances of 'Color' should be created using an 8-digit hexadecimal integer +(such as '0xFFFFFFFF')._ + +#### Description + +The analyzer produces this diagnostic when the argument to the constructor +of the `Color` class is a literal integer that isn't represented as an +8-digit hexadecimal integer. + +#### Example + +The following code produces this diagnostic because the argument (`1`) +isn't represented as an 8-digit hexadecimal integer: + +```dart +import 'package:flutter/material.dart'; + +Color c = Color([!1!]); +``` + +#### Common fixes + +Convert the representation to be an 8-digit hexadecimal integer: + +```dart +import 'package:flutter/material.dart'; + +Color c = Color(0x00000001); +``` + +### use_function_type_syntax_for_parameters + +_Use the generic function type syntax to declare the parameter '{0}'._ + +#### Description + +The analyzer produces this diagnostic when the older style function-valued +parameter syntax is used. + +#### Example + +The following code produces this diagnostic because the function-valued +parameter `f` is declared using an older style syntax: + +```dart +void g([!bool f(String s)!]) {} +``` + +#### Common fixes + +Use the generic function type syntax to declare the parameter: + +```dart +void g(bool Function(String) f) {} +``` + +### use_key_in_widget_constructors + +_Constructors for public widgets should have a named 'key' parameter._ + +#### Description + +The analyzer produces this diagnostic when a constructor in a subclass of +`Widget` that isn't private to its library doesn't have a parameter named +`key`. + +#### Example + +The following code produces this diagnostic because the constructor for +the class `MyWidget` doesn't have a parameter named `key`: + +```dart +import 'package:flutter/material.dart'; + +class MyWidget extends StatelessWidget { + [!MyWidget!]({required int height}); +} +``` + +The following code produces this diagnostic because the default +constructor for the class `MyWidget` doesn't have a parameter named `key`: + +```dart +import 'package:flutter/material.dart'; + +class [!MyWidget!] extends StatelessWidget {} +``` + +#### Common fixes + +Add a parameter named `key` to the constructor, explicitly declaring the +constructor if necessary: + +```dart +import 'package:flutter/material.dart'; + +class MyWidget extends StatelessWidget { + MyWidget({super.key, required int height}); +} +``` + +### use_rethrow_when_possible + +_Use 'rethrow' to rethrow a caught exception._ + +#### Description + +The analyzer produces this diagnostic when a caught exception is thrown +using a `throw` expression rather than a `rethrow` statement. + +#### Example + +The following code produces this diagnostic because the caught exception +`e` is thrown using a `throw` expression: + +```dart +void f() { + try { + // ... + } catch (e) { + [!throw e!]; + } +} +``` + +#### Common fixes + +Use `rethrow` instead of `throw`: + +```dart +void f() { + try { + // ... + } catch (e) { + rethrow; + } +} +``` + +### use_string_in_part_of_directives + +_The part-of directive uses a library name._ + +#### Description + +The analyzer produces this diagnostic when a `part of` directive uses a +library name to refer to the library that the part is a part of. + +#### Example + +Given a file named `lib.dart` that contains the following: + +```dart +library lib; + +part 'test.dart'; +``` + +The following code produces this diagnostic because the `part of` +directive uses the name of the library rather than the URI of the library +it's part of: + +```dart +[!part of lib;!] +``` + +#### Common fixes + +Use a URI to reference the library: + +```dart +part of 'lib.dart'; +``` + +### use_super_parameters + +_Use super-initializer parameters where possible._ + +#### Description + +The analyzer produces this diagnostic when a parameter to a constructor is +passed to a super constructor without being referenced or modified and a +`super` parameter isn't used. + +#### Example + +The following code produces this diagnostic because the parameters of the +constructor for `B` are only used as arguments to the super constructor: + +```dart +class A { + A({int? x, int? y}); +} +class B extends A { + [!B!]({int? x, int? y}) : super(x: x, y: y); +} +``` + +#### Common fixes + +Use a `super` parameter to pass the arguments: + +```dart +class A { + A({int? x, int? y}); +} +class B extends A { + B({super.x, super.y}); +} +``` + +### valid_regexps + +_Invalid regular expression syntax._ + +#### Description + +The analyzer produces this diagnostic when the string passed to the +default constructor of the class `RegExp` doesn't contain a valid regular +expression. + +A regular expression created with invalid syntax will throw a +`FormatException` at runtime. + +#### Example + +The following code produces this diagnostic because the regular expression +isn't valid: + +```dart +var r = RegExp([!r'('!]); +``` + +#### Common fixes + +Fix the regular expression: + +```dart +var r = RegExp(r'\('); +``` + +### void_checks + +_Assignment to a variable of type 'void'._ + +#### Description + +The analyzer produces this diagnostic when a value is assigned to a +variable of type `void`. + +It isn't possible to access the value of such a variable, so the +assignment has no value. + +#### Example + +The following code produces this diagnostic because the field `value` has +the type `void`, but a value is being assigned to it: + +```dart +class A { + T? value; +} + +void f(A a) { + [!a.value = 1!]; +} +``` + +The following code produces this diagnostic because the type of the +parameter `p` in the method `m` is `void`, but a value is being assigned +to it in the invocation: + +```dart +class A { + void m(T p) { } +} + +void f(A a) { + a.m([!1!]); +} +``` + +#### Common fixes + +If the type of the variable is incorrect, then change the type of the +variable: + +```dart +class A { + T? value; +} + +void f(A a) { + a.value = 1; +} +``` + +If the type of the variable is correct, then remove the assignment: + +```dart +class A { + T? value; +} + +void f(A a) {} +``` diff --git a/src/content/tools/non-promotion-reasons.md b/src/content/tools/non-promotion-reasons.md index 6d13181e4..a7e51fb30 100644 --- a/src/content/tools/non-promotion-reasons.md +++ b/src/content/tools/non-promotion-reasons.md @@ -185,7 +185,7 @@ you'd want to do a null check to see whether `this` is `null`: **Example:** ```dart tag=bad -extension E on int? { +extension on int? { int get valueOrZero { return this == null ? 0 : this; // ERROR } @@ -203,10 +203,11 @@ extension E on int? { Create a local variable to hold the value of `this`, then perform the null check. + ```dart tag=good -extension E on int? { +extension on int? { int get valueOrZero { - final self = this; + [!final self = this;!] return self == null ? 0 : self; } } @@ -229,14 +230,14 @@ non-private fields cannot be promoted. **Example:** ```dart tag=bad -class C { - final int? n; - C(this.n); +class Example { + final int? value; + Example(this.value); } -test(C c) { - if (c.n != null) { - print(c.n + 1); // ERROR +void test(Example x) { + if (x.value != null) { + print(x.value + 1); // ERROR } } ``` @@ -244,7 +245,7 @@ test(C c) { **Message:** ```plaintext -'n' refers to a public property so it couldn't be promoted. +'value' refers to a public property so it couldn't be promoted. ``` **Solution:** @@ -252,15 +253,16 @@ test(C c) { Making the field private lets the compiler be sure that no outside libraries could possibly override its value, so it's safe to promote. + ```dart tag=good -class C { - final int? _n; - C(this._n); +class Example { + final int? [!_value!]; + Example(this._value); } -test(C c) { - if (c._n != null) { - print(c._n + 1); // OK +void test(Example x) { + if (x._value != null) { + print(x._value + 1); } } ``` @@ -279,7 +281,7 @@ to a non-nullable type. **Example:** ```dart tag=bad -class C { +class Example { int? _mutablePrivateField; Example(this._mutablePrivateField); @@ -301,9 +303,10 @@ class C { Make the field `final`: + ```dart tag=good class Example { - final int? _immutablePrivateField; + [!final!] int? _immutablePrivateField; Example(this._immutablePrivateField); void f() { @@ -319,21 +322,23 @@ class Example { **The cause:** You're trying to promote a getter, but only instance *fields* can be promoted, not instance getters. -The compiler has no way to guarantee that a getter returns the same result every time. -Because their stability can't be confirmed, getters are not safe to promote. +The compiler has no way to guarantee that +a getter returns the same result every time. +Because their stability can't be confirmed, +getters are not safe to promote. **Example:** ```dart tag=bad import 'dart:math'; -abstract class C { - int? get _i => Random().nextBool() ? 123 : null; +abstract class Example { + int? get _value => Random().nextBool() ? 123 : null; } -void f(C c) { - if (c._i != null) { - print(c._i.isEven); // ERROR +void f(Example x) { + if (x._value != null) { + print(x._value.isEven); // ERROR } } ``` @@ -341,24 +346,25 @@ void f(C c) { **Message:** ```plaintext -'_i' refers to a getter so it couldn't be promoted. +'_value' refers to a getter so it couldn't be promoted. ``` **Solution:** Assign the getter to a local variable: + ```dart tag=good import 'dart:math'; -abstract class C { - int? get _i => Random().nextBool() ? 123 : null; +abstract class Example { + int? get _value => Random().nextBool() ? 123 : null; } -void C c) { - final i = c._i; - if (i != null) { - print(i.isEven); // OK +void f(Example x) { + [!final value = x._value;!] + if (value != null) { + print(value.isEven); // OK } } ``` @@ -381,9 +387,8 @@ will return the same value each time it's called. **Example:** ```dart tag=bad -class C { +class Example { external final int? _externalField; - C(this._externalField); void f() { if (_externalField != null) { @@ -396,20 +401,20 @@ class C { **Message:** ```plaintext -'externalField' refers to an external field so it couldn't be promoted. +'_externalField' refers to an external field so it couldn't be promoted. ``` **Solution:** Assign the external field's value to a local variable: + ```dart tag=good -class C { +class Example { external final int? _externalField; - C(this._externalField); void f() { - final i = this._externalField; + [!final i = _externalField;!] if (i != null) { print(i.isEven); // OK } @@ -439,7 +444,7 @@ class Override implements Example { int? get _overridden => Random().nextBool() ? 1 : null; } -void f(Example x) { +void testParity(Example x) { if (x._overridden != null) { print(x._overridden.isEven); // ERROR } @@ -449,7 +454,7 @@ void f(Example x) { **Message:** ```plaintext -'overriden' couldn't be promoted because there is a conflicting getter in class 'Override' +'_overriden' couldn't be promoted because there is a conflicting getter in class 'Override'. ``` **Solution**: @@ -458,6 +463,7 @@ If the getter and field are related and need to share their name (like when one of them overrides the other, as in the example above), then you can enable type promotion by assigning the value to a local variable: + ```dart tag=good import 'dart:math'; @@ -471,8 +477,8 @@ class Override implements Example { int? get _overridden => Random().nextBool() ? 1 : null; } -void f(Example x) { - final i = x._overridden; +void testParity(Example x) { + [!final i = x._overridden;!] if (i != null) { print(i.isEven); // OK } @@ -524,6 +530,7 @@ void main() { If the field and the conflicting entity are truly unrelated, you can work around the problem by giving them different names: + ```dart tag=good class Example { final int? _i; @@ -531,7 +538,7 @@ class Example { } class Unrelated { - int? get _j => Random().nextBool() ? 1 : null; + int? [!get _j!] => Random().nextBool() ? 1 : null; } void f(Example x) { @@ -583,6 +590,7 @@ If the fields are actually related and need to share a name, then you can enable type promotion by assigning the value to a final local variable to promote: + ```dart tag=good class Example { final int? _overridden; @@ -595,9 +603,9 @@ class Override implements Example { } void f(Example x) { - final i = x._overridden; + [!final i = x._overridden;!] if (i != null) { - print(i.isEven); // ERROR + print(i.isEven); // OK } } ``` @@ -662,6 +670,7 @@ The failure can also occur between fields in Define the getter in question so that `noSuchMethod` doesn't have to implicitly handle its implementation: + ```dart tag=good import 'package:mockito/mockito.dart'; @@ -672,7 +681,7 @@ class Example { class MockExample extends Mock implements Example { @override - late final int? _i; // Add a definition for Example's _i getter. + [!late final int? _i;!] } void f(Example x) { diff --git a/src/content/tools/sdk.md b/src/content/tools/sdk.md index e8bc101f7..3696c6114 100644 --- a/src/content/tools/sdk.md +++ b/src/content/tools/sdk.md @@ -50,5 +50,5 @@ go to [the SDK issue tracker][sdk-issues]. [Dart libraries]: /libraries [flutter]: {{site.flutter-docs}}/get-started/install [site SDK version]: {{site.dart-api}}/{{site.sdkInfo.channel}}/{{site.sdkInfo.version}}/index.html -[readme]: ({{site.repo.dart.sdk}}/blob/main/README.dart-sdk) -[sdk-issues]: ({{site.repo.dart.sdk}}/issues) +[readme]: {{site.repo.dart.sdk}}/blob/main/README.dart-sdk +[sdk-issues]: {{site.repo.dart.sdk}}/issues diff --git a/src/content/tutorials/index.md b/src/content/tutorials/index.md index 5bbbbf3ea..1b65038e4 100644 --- a/src/content/tutorials/index.md +++ b/src/content/tutorials/index.md @@ -7,33 +7,29 @@ description: 撰写 Dart 应用的教程文档。 These tutorials teach you how to use the Dart language, tools, and APIs to build applications. -If you want a hands-on coding experience, try a -**[codelab](/codelabs)**. -这些指南会教你如何使用 Dart 语言,工具,以及 API -构建应用程序。如果你想要一份体验动手编码的指导,请尝试 -**[codelab](/codelabs)** 。 +这些教程会教你如何使用 Dart 语言、工具以及 API +来构建应用程序。 -## The basics +## Learn the basics {:#basics} -## 基础 +## 学习基础知识 The following tours assume a basic familiarity with the Dart language, -which you can get from skimming the -[language tour](/language). -Next, learn about futures by following the -[asynchronous programming codelab](/codelabs/async-await). +which you can get from skimming the [language tour](/language). +Next, to learn about futures, try the +[asynchronous programming tutorial](/libraries/async/async-await). 以下内容假定你对 Dart 有基本的了解, 你可以通过浏览 [Dart 简介](/language) 对 Dart 语言有一个初步了解, -接下来,请跟随 [异步编程 codelab](/codelabs/async-await) 来学习 Future。 +接下来,请跟随 [异步编程教程](/libraries/async/async-await) 来学习 Future。 Once you're familiar with the language and futures, -learn about _streams_ and _packages_, +learn about _iterables_, _streams_, and _packages_, which are fundamental to most Dart programs. 当你熟悉 Dart 语言以及 Future 后, -就可以进一步了解 _Stream_ 和 _Package_, +就可以进一步了解 _Iterable_、_Stream_ 和 _Package_, 它们是众多 Dart 程序的基础。
@@ -53,16 +49,42 @@ which are fundamental to most Dart programs.
-## Server-side Dart tutorials + +## Build server-side apps {:#server} ## Dart 服务端教程 {% include 'server-tutorials.md' %} -## More tutorials + +## Keep learning -## 更多学习教程 +## 持续学习 -Check out the [Flutter codelabs and tutorials]({{site.flutter-docs}}/codelabs). +To get more experience developing with Dart, +try more of the available tutorials! -请查阅 [Flutter codelabs and tutorials]({{site.flutter-docs}}/codelabs)。 +尝试更多教程,来学习更多使用 Dart 开发的经验! + +
+
+

Dart cheatsheetDart 速查表

+

Quickly try out some of Dart's unique language features.

+

快速体验 Dart 独特的语言特性。

+
+
+

记录 (Record) 和模式匹配 (Pattern)

+

Discover Dart's support for records and patterns.

+

探索 Dart 对记录 (Record) 和模式匹配 (Pattern) 的支持。

+
+
+

Iterable collections可迭代集合

+

Learn to analyze and manipulate data stored in collections.

+

学习分析和处理存储在数据集中的数据。

+
+
+

Flutter codelabs and tutorialsFlutter codelabs 和教程

+

Expand your Dart skills by building Flutter apps.

+

通过构建 Flutter 应用来拓展你的 Dart 技能。

+
+
diff --git a/src/content/tutorials/server/cmdline.md b/src/content/tutorials/server/cmdline.md index dcdde34bc..49ee78028 100644 --- a/src/content/tutorials/server/cmdline.md +++ b/src/content/tutorials/server/cmdline.md @@ -35,8 +35,8 @@ the [`Future`]({{_api}}/dart-async/Future-class.html) and [`Stream`]({{_api}}/dart-async/Stream-class.html) classes for asynchronous support. To learn more about these features, see the -[asynchronous programming codelab](/codelabs/async-await) and the -[streams tutorial](/tutorials/language/streams). +[asynchronous programming tutorial](/libraries/async/async-await) and the +[streams tutorial](/libraries/async/using-streams). ::: This tutorial teaches you how to build command-line apps diff --git a/src/content/tutorials/server/fetch-data.md b/src/content/tutorials/server/fetch-data.md index c76214552..57db6ea9f 100644 --- a/src/content/tutorials/server/fetch-data.md +++ b/src/content/tutorials/server/fetch-data.md @@ -230,7 +230,7 @@ access the network and perform potentially time-consuming operations, therefore they do so asynchronously and return a [`Future`][]. If you haven't encountered futures yet, you can learn about them—as well as the `async` and `await` keywords—in the -[asynchronous programming codelab](/codelabs/async-await). +[asynchronous programming tutorial](/libraries/async/async-await). ::: diff --git a/src/content/tutorials/server/get-started.md b/src/content/tutorials/server/get-started.md index 926b2f2ba..c97d7be42 100644 --- a/src/content/tutorials/server/get-started.md +++ b/src/content/tutorials/server/get-started.md @@ -208,6 +208,7 @@ Use the `dart compile` tool to AOT compile the program to machine code: ```console $ dart compile exe bin/cli.dart ``` + Notice how the compiled program starts instantly, completing quickly: 看看编译后的程序启动有多快: @@ -229,17 +230,9 @@ Check out these resources: 检索这些资源: -* Additional tutorials and codelabs for Dart - - 其它额外的一些 Dart 教程和指引 - - * [Tutorials](/tutorials) - - [教程](/tutorials) - - * [Codelabs](/codelabs) +* Dart [tutorials](/tutorials) - [指引](/codelabs) + Dart [教程](/tutorials) * Dart language, libraries, and conventions diff --git a/src/content/web/get-started.md b/src/content/web/get-started.md index 1d720af85..c4164a4f9 100644 --- a/src/content/web/get-started.md +++ b/src/content/web/get-started.md @@ -186,9 +186,7 @@ Check out these resources: * [Web libraries and packages](/web/libraries) * [`package:web` overview](/interop/js-interop/package-web) * [Introduction to the DOM][] -* Tutorials and codelabs for Dart - * [Tutorials](/tutorials) - * [Codelabs](/codelabs) +* Dart [tutorials](/tutorials) If you get stuck, find help at [Community and support.](/community) diff --git a/src/content/web/wasm.md b/src/content/web/wasm.md index fc0ee0f79..7bd38e42b 100644 --- a/src/content/web/wasm.md +++ b/src/content/web/wasm.md @@ -41,6 +41,18 @@ restrictions: contain a temporary workaround. For details, see [webdev issue 2206]({{site.repo.dart.org}}/webdev/issues/2296). +### Supported packages + +To find Wasm-compatible packages, +use the [`wasm-ready`][] filter on [pub.dev][]. + +A package is "wasm-ready" if it doesn't import non-Wasm compliant libraries +like `dart:html`, `dart:js`, etc. You can find the full list of unallowed +libraries on the [JS interop page](/interop/js-interop/#next-generation-js-interop). + +[`wasm-ready`]: {{site.pub-pkg}}?q=is%3Awasm-ready +[pub.dev]: {{site.pub}} + ## Compiling your web app to Wasm {:#compiling-to-wasm} We've landed support in the `dart` CLI for invoking the