-
Notifications
You must be signed in to change notification settings - Fork 182
馃 chore: sync skills directory from dart-lang/skills #241
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,7 +4,7 @@ description: >- | |
| Cross-platform file and directory path manipulation, segment splitting, extension extraction, and context conversion using `package:path` and `package:file`. Use when writing, inspecting, joining, splitting, or refactoring file paths, directory names, or extensions, or replacing raw string path operations (`.split('/')`, `'$dir/$file'`, `.endsWith('.ext')`, `.replaceAll('\\', '/')`). Don't use for HTTP network URI routing, database query strings, or non-path string processing. | ||
| metadata: | ||
| model: models/gemini-3.1-pro-preview | ||
| last_modified: Sun, 06 Sep 2026 07:14:00 GMT | ||
| last_modified: Wed, 23 Sep 2026 22:10:00 GMT | ||
| --- | ||
|
|
||
| # Safe Cross-Platform Path Manipulation in Dart | ||
|
|
@@ -60,10 +60,14 @@ metadata: | |
| false positives on partial substring names (e.g. `barfoo/`). | ||
|
|
||
| ### Root and Directory Prefixes | ||
| * **Prefer**: `p.split(path).first == 'foo'` or `p.isWithin('foo', path)` | ||
| * **Avoid**: `path.startsWith('foo/')` | ||
| * **Why**: Fails on Windows separators and misses relative prefix variants such | ||
| as `./foo/`. | ||
| * **Prefer**: `if (p.split(path) case ['foo', ...])` (or `case ['foo', ...final rest]` when extracting tail segments), or `p.isWithin('foo', path)` | ||
| * **Avoid**: `path.startsWith('foo/')` or `p.split(path).first == 'foo'` | ||
| * **Why**: String prefix matching fails on Windows separators (`foo\bar`). Calling | ||
| `p.split(path).first` throws a `StateError` on empty lists and requires | ||
| separate `.skip(1)` slicing, whereas list patterns safely check non-emptiness, | ||
| match multi-segment prefixes, and optionally bind `...final rest` in a single | ||
| step. When unnormalized relative prefixes like `./foo/bar` may appear, use | ||
| `p.isWithin('foo', path)` (or `p.split(p.normalize(path))`). | ||
|
|
||
| ### File Extensions | ||
| * **Prefer**: `p.extension(path) == '.wasm'` | ||
|
|
@@ -188,7 +192,7 @@ String insertContentHash(String filename, String hash) { | |
|
|
||
| ### Path Refactoring Checklist | ||
| - [ ] Replace string interpolation (`'$dir/$file'`) with `p.join(dir, file)`. | ||
| - [ ] Replace `.contains('dir/')` and `.startsWith('dir/')` with `p.split(path)` segment checks or `p.isWithin(parent, child)`. | ||
| - [ ] Replace `.contains('dir/')` and `.startsWith('dir/')` with `p.split(path)` list pattern checks (`case ['dir', ...final rest]`) or `p.isWithin(parent, child)`. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The checklist item suggests replacing both |
||
| - [ ] Replace `.replaceAll(r'\', '/')` with `p.posix.joinAll(p.split(path))` (or `p.url.joinAll`). | ||
| - [ ] Replace `.endsWith('.ext')` on file paths with `p.extension(path) == '.ext'`. | ||
| - [ ] Replace manual dot-index slicing with `p.withoutExtension(path)` and `p.extension(path, [level])`. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,13 +4,13 @@ description: >- | |
| Applies Dart 3 pattern matching, switch expressions, and destructuring | ||
| idiomatically to validate data schemas, handle algebraic data types, and | ||
| decompose control flow. Use when refactoring complex if-else chains, | ||
| parsing polymorphic JSON or API responses, destructuring Records or Maps, or | ||
| enforcing exhaustiveness on sealed classes. Don't use for simple boolean | ||
| conditions, single-variable type promotion (use `is`), or basic collection | ||
| filtering. | ||
| parsing polymorphic JSON or API responses, destructuring Lists, URI/path | ||
| segments, String.split() tokens, Records, or Maps, or enforcing exhaustiveness | ||
| on sealed classes. Don't use for simple boolean conditions, single-variable | ||
| type promotion (use `is`), or basic collection filtering. | ||
| metadata: | ||
| model: models/gemini-3.1-pro-preview | ||
| last_modified: Sun, 06 Sep 2026 06:43:00 GMT | ||
| last_modified: Wed, 23 Sep 2026 22:10:00 GMT | ||
| --- | ||
| # Implementing Dart Patterns | ||
|
|
||
|
|
@@ -27,6 +27,7 @@ metadata: | |
| Apply specific pattern types based on the data structure and desired outcome. Follow these conditional guidelines: | ||
|
|
||
| * **If validating and extracting from deserialized data (e.g., JSON):** Use Map, List, and Object patterns to validate schema structure and destructure properties in a single step. | ||
| * **If inspecting URL/path segments (`uri.pathSegments`, `p.split(path)`) or `String.split()` tokens:** Use List patterns with rest elements (`['api', 'comments', ...]`, `['assets', ...final rest]`, `[..., final parent, _]`) instead of manual `.length` checks, `.first`, `.skip(1)`, or `length - N` index arithmetic. | ||
| * **If handling polymorphic payloads or responses:** Use `switch` expressions over map discriminant keys to deserialize into `sealed` class hierarchies. | ||
| * **If handling multiple return values:** Use Record patterns to destructure fields directly into local variables. | ||
| * **If executing type-specific behavior (Algebraic Data Types):** Use Object patterns combined with `sealed` classes to ensure exhaustiveness. | ||
|
|
@@ -147,10 +148,10 @@ Use standard boolean operators (`if (code >= 200 && code < 300)`) instead of `if | |
| ### Task Progress: Implementing Pattern Matching | ||
| Copy this checklist to track progress when implementing complex pattern matching logic: | ||
|
|
||
| - [ ] Identify the data structure being evaluated (JSON, Record, Class, Enum). | ||
| - [ ] Identify the data structure being evaluated (JSON, List/Segments, Record, Class, Enum). | ||
| - [ ] Select the appropriate switch construct (Expression for values, Statement for side-effects). | ||
| - [ ] Define the required patterns (Object, Map, List, Record). | ||
| - [ ] Extract required data using Variable patterns (`var x`, `:var y`). | ||
| - [ ] Extract required data using Variable patterns (`var x`, `:var y`, `...final rest`). | ||
| - [ ] Apply Guard clauses (`when condition`) for logic that cannot be expressed via patterns. | ||
| - [ ] Handle unmatched cases using a Wildcard (`_`) or `default` clause (if not using a sealed class). | ||
| - [ ] Run static analyzer for exhaustiveness and dead code (`dart analyze`). | ||
|
|
@@ -189,6 +190,21 @@ might be omitted entirely from the payload (rather than explicitly passed as | |
| `'key': null`), destructure required keys via the pattern and extract optional | ||
| fields directly from the matched submap. | ||
|
|
||
| ### List and Path Segment Destructuring | ||
| Use `if-case` with list rest elements (`...final rest`) to validate prefixes and | ||
| extract remaining elements without a 2-arm `_ => null` switch or manual `.first` | ||
| and `.skip(1)` indexing. | ||
|
|
||
| ```dart | ||
| String? resolveAllowedAssetSubpath(List<String> segments) { | ||
| if (segments case ['assets', ...final rest] | ||
| when rest.isNotEmpty && !rest.contains('..')) { | ||
| return rest.join('/'); | ||
| } | ||
| return null; | ||
| } | ||
|
Comment on lines
+199
to
+205
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While this is an illustrative example of list pattern matching, using |
||
| ``` | ||
|
|
||
| ### Algebraic Data Types (Sealed Classes) | ||
| Use Object patterns with switch expressions to handle family types exhaustively. | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| 26b2dcc5654cbbc3b2ec56ea94719469bc8bae9e | ||
| 82a49602fe18cecfe41859592af600cb9d875e40 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When dealing with absolute paths,
p.split(path)will include the root directory (such as'/'on POSIX or'C:\\'on Windows) as the first element in the returned list. Consequently, a pattern match likecase ['foo', ...]will fail to match absolute paths even if they start with'foo'relative to the root. To handle absolute paths safely, consider converting them to relative paths usingp.relative(path, from: root)before performing list pattern matching, or usep.isWithin.