diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index 719c5c9328..3853d6258a 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -268,6 +268,7 @@ jobs: osv-scanner scan source --lockfile=pubspec.lock dart analyze --no-fatal-warnings flutter test + ../../scripts/validate-dart-examples.sh . ;; apple|swift) if [ ! -f .swift-format ]; then @@ -337,6 +338,7 @@ jobs: dart pub get osv-scanner scan source --lockfile=pubspec.lock dart analyze --no-fatal-warnings + ../../scripts/validate-dart-examples.sh . ;; go) go mod tidy || true diff --git a/scripts/validate-dart-examples.sh b/scripts/validate-dart-examples.sh new file mode 100755 index 0000000000..7a39810499 --- /dev/null +++ b/scripts/validate-dart-examples.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +set -euo pipefail + +sdk_dir="${1:-.}" +sdk_dir="$(cd "$sdk_dir" && pwd)" + +tmp="$(mktemp -d "$sdk_dir/docs-examples.XXXXXX")" +trap 'rm -rf "$tmp"' EXIT + +count=0 +while IFS= read -r example; do + name="${example#"$sdk_dir/docs/examples/"}" + name="${name%.md}" + file="$tmp/${name//[^a-zA-Z0-9]/_}.dart" + + awk ' + /^```dart$/ { in_block = 1; next } + /^```$/ && in_block { exit } + in_block && /^import / { imports = imports $0 "\n"; next } + in_block { body = body " " $0 "\n" } + END { + if (body == "") exit + printf "// ignore_for_file: deprecated_member_use_from_same_package, unused_local_variable\n%s\nFuture main() async {\n%s}\n", imports, body + } + ' "$example" > "$file" + + if [[ ! -s "$file" ]]; then + rm -f "$file" + continue + fi + + count=$((count + 1)) +done < <(find "$sdk_dir/docs/examples" -type f -name '*.md' | sort) + +echo "Analyzing $count generated Dart examples" +(cd "$sdk_dir" && dart analyze --fatal-warnings "$tmp") diff --git a/templates/dart/docs/example.md.twig b/templates/dart/docs/example.md.twig index 770415c9cb..a47bac0368 100644 --- a/templates/dart/docs/example.md.twig +++ b/templates/dart/docs/example.md.twig @@ -1,9 +1,9 @@ ```dart -{% if (method | methodType) == 'upload' %} -import 'dart:io'; +{% if (method | methodType) == 'location' %} +import 'dart:typed_data'; {% endif %} import 'package:{{ language.params.packageName }}/{{ language.params.packageName }}.dart'; -{% if method.method.value != 'delete' and (method | methodType) not in ['webAuth', 'location'] and (method | getValidResponseModels)|length <= 1 and (method | responseModel) %} +{% if method.method.value != 'delete' and (method | methodType) not in ['webAuth', 'location'] and (method | getValidResponseModels)|length <= 1 and (method | responseModel) and (method | responseModel) != 'any' and not (method | textResponse) %} import 'package:{{ language.params.packageName }}/models.dart' as models; {% endif %} {% set hasEnumParam = false %} @@ -15,10 +15,6 @@ import 'package:{{ language.params.packageName }}/models.dart' as models; {% if hasEnumParam %} import 'package:{{ language.params.packageName }}/enums.dart' as enums; {% endif %} -{% if (method | parameters('all')) | hasPermissionParam %} -import 'package:{{ language.params.packageName }}/permission.dart'; -import 'package:{{ language.params.packageName }}/role.dart'; -{% endif %} Client client = Client() {%~ if [(method | securitySchemes)]|length > 0 %} @@ -32,7 +28,7 @@ Client client = Client() {{ service.name | caseUcfirst }} {{ service.name | caseCamel }} = {{service.name | caseUcfirst}}(client); -{% if method.method.value != 'delete' and (method | methodType) != 'webAuth' %}{% if (method | methodType) == 'location' %}Uint8List{% elseif (method | textResponse) %}String{% elseif (method | getValidResponseModels)|length > 1 %}dynamic{% else %}models.{{ (method | responseModel) | caseUcfirst | overrideIdentifier }}{% endif %} result = {% endif %}await {{ service.name | caseCamel }}.{{ (method | methodName) | caseCamel }}({% if (method | parameters('all')) | length == 0 %});{% endif %} +{% if method.method.value != 'delete' and (method | methodType) != 'webAuth' %}{% if (method | methodType) == 'location' %}Uint8List result = {% elseif (method | textResponse) %}String result = {% elseif (method | getValidResponseModels)|length > 1 or (method | responseModel) == 'any' %}dynamic result = {% elseif (method | responseModel) %}models.{{ (method | responseModel) | caseUcfirst | overrideIdentifier }} result = {% endif %}{% endif %}await {{ service.name | caseCamel }}.{{ (method | methodName) | caseCamel }}({% if (method | parameters('all')) | length == 0 %});{% endif %} {%~ for parameter in (method | parameters('all')) %} {{ parameter.name | caseCamel | overrideIdentifier }}: {% if (parameter | enumValues) | length > 0 %}{{ parameter | enumExample }}{% else %}{{ parameter | paramExample | replace({'': (parameter.name | caseCamel) }) | raw }}{% endif %},{% if not parameter.required %} // (optional){% endif %} diff --git a/templates/flutter/docs/example.md.twig b/templates/flutter/docs/example.md.twig index 6f80a079e7..c7e146be92 100644 --- a/templates/flutter/docs/example.md.twig +++ b/templates/flutter/docs/example.md.twig @@ -1,13 +1,11 @@ ```dart -{% if (method | methodType) in ['upload', 'location'] %} -import 'dart:io'; -{% endif %} {% if (method | methodType) == 'location' %} +import 'dart:io'; import 'dart:typed_data'; import 'package:flutter/material.dart'; {% endif %} import 'package:{{ language.params.packageName }}/{{ language.params.packageName }}.dart'; -{% if method.method.value != 'delete' and (method | methodType) not in ['webAuth', 'location'] and (method | getValidResponseModels)|length <= 1 and (method | responseModel) %} +{% if method.method.value != 'delete' and (method | methodType) not in ['webAuth', 'location'] and (method | getValidResponseModels)|length <= 1 and (method | responseModel) and (method | responseModel) != 'any' and not (method | textResponse) %} import 'package:{{ language.params.packageName }}/models.dart' as models; {% endif %} {% set hasEnumParam = false %} @@ -19,10 +17,6 @@ import 'package:{{ language.params.packageName }}/models.dart' as models; {% if hasEnumParam %} import 'package:{{ language.params.packageName }}/enums.dart' as enums; {% endif %} -{% if (method | parameters('all')) | hasPermissionParam %} -import 'package:{{ language.params.packageName }}/permission.dart'; -import 'package:{{ language.params.packageName }}/role.dart'; -{% endif %} Client client = Client() {%~ if [(method | securitySchemes)]|length > 0 %} @@ -62,7 +56,7 @@ FutureBuilder( }, ); {% else %} -{% if method.method.value != 'delete' and (method | methodType) != 'webAuth' %}{% if (method | methodType) == 'location' %}Uint8List{% elseif (method | textResponse) %}String{% elseif (method | getValidResponseModels)|length > 1 %}dynamic{% else %}models.{{ (method | responseModel) | caseUcfirst | overrideIdentifier }}{% endif %} result = {% endif %}await {{ service.name | caseCamel }}.{{ (method | methodName) | caseCamel }}({% if (method | parameters('all')) | length == 0 %});{% endif %} +{% if method.method.value != 'delete' and (method | methodType) != 'webAuth' %}{% if (method | methodType) == 'location' %}Uint8List result = {% elseif (method | textResponse) %}String result = {% elseif (method | getValidResponseModels)|length > 1 or (method | responseModel) == 'any' %}dynamic result = {% elseif (method | responseModel) %}models.{{ (method | responseModel) | caseUcfirst | overrideIdentifier }} result = {% endif %}{% endif %}await {{ service.name | caseCamel }}.{{ (method | methodName) | caseCamel }}({% if (method | parameters('all')) | length == 0 %});{% endif %} {%~ for parameter in (method | parameters('all')) %} {{ parameter.name | caseCamel | overrideIdentifier}}: {% if (parameter | enumValues) | length > 0%}{{ parameter | enumExample }}{% else %}{{ parameter | paramExample | replace({'': (parameter.name | caseCamel) }) | raw }}{% endif %},{% if not parameter.required %} // optional{% endif %}